// Path: src/main/java/com/github/mkopylec/errorest/exceptions/ExternalHttpRequestException.java
// public class ExternalHttpRequestException extends HttpStatusCodeException {
// 
//     private static final Logger log = getLogger(ExternalHttpRequestException.class);
// 
//     protected final HttpMethod method;
//     protected final String url;
//     protected final ObjectMapper jsonMapper;
//     protected final XmlMapper xmlMapper;
//     protected Errors errors;
// 
//     public ExternalHttpRequestException(HttpMethod method, String url, HttpStatus statusCode, String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset, ObjectMapper jsonMapper, XmlMapper xmlMapper) {
//         super(statusCode, statusText, responseHeaders, responseBody, responseCharset);
//         this.method = method;
//         this.url = url;
//         this.jsonMapper = jsonMapper;
//         this.xmlMapper = xmlMapper;
//     }
// 
//     public Errors getResponseBodyAsErrors() {
//         if (errors != null) {
//             return errors;
//         }
//         errors = parseResponseBody();
//         if (errors == null) {
//             return emptyErrors();
//         }
//         return errors;
//     }
// 
//     @Override
//     public String getMessage() {
//         return "An external HTTP request has failed: " + method + " " + url + " " + getStatusCode() + ". Response body: " + getResponseBodyAsString();
//     }
// 
//     protected Errors parseResponseBody() {
//         try {
//             if (hasContentType(APPLICATION_JSON)) {
//                 return jsonMapper.readValue(getResponseBodyAsString(), Errors.class);
//             }
//             if (hasContentType(APPLICATION_XML)) {
//                 return xmlMapper.readValue(getResponseBodyAsString(), Errors.class);
//             }
//             throw new IOException("Incompatible HTTP response " + CONTENT_TYPE + " header: " + getResponseHeaders().getContentType());
//         } catch (IOException e) {
//             log.warn("Cannot convert HTTP response body to {}: {}", Errors.class.getName(), e.getMessage());
//             return null;
//         }
//     }
// 
//     protected boolean hasContentType(MediaType mediaType) {
//         MediaType contentType = getResponseHeaders().getContentType();
//         return contentType != null && contentType.includes(mediaType);
//     }
// }


import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.github.mkopylec.errorest.exceptions.ExternalHttpRequestException;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.List;
import static org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.json;
import static org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.xml;
package com.github.mkopylec.errorest.client;




public class ErrorestTemplate extends RestTemplate {

    protected ObjectMapper jsonMapper = json().build();
    protected XmlMapper xmlMapper = xml().build();

    public ErrorestTemplate() {
        super();
    }

    public ErrorestTemplate(ClientHttpRequestFactory requestFactory) {
        super(requestFactory);
    }

    public ErrorestTemplate(List<HttpMessageConverter<?>> messageConverters) {
        super(messageConverters);
    }

    public void setJsonMapper(ObjectMapper jsonMapper) {
        this.jsonMapper = jsonMapper;
    }

    public void setXmlMapper(XmlMapper xmlMapper) {
        this.xmlMapper = xmlMapper;
    }

    @Override
    protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor) throws RestClientException {
        try {
            return super.doExecute(url, method, requestCallback, responseExtractor);
        } catch (HttpStatusCodeException ex) {
            throw createExternalHttpRequestException(method, url, ex);
        }
    }

// Path: src/main/java/com/github/mkopylec/errorest/exceptions/ExternalHttpRequestException.java
// public class ExternalHttpRequestException extends HttpStatusCodeException {
// 
//     private static final Logger log = getLogger(ExternalHttpRequestException.class);
// 
//     protected final HttpMethod method;
//     protected final String url;
//     protected final ObjectMapper jsonMapper;
//     protected final XmlMapper xmlMapper;
//     protected Errors errors;
// 
//     public ExternalHttpRequestException(HttpMethod method, String url, HttpStatus statusCode, String statusText, HttpHeaders responseHeaders, byte[] responseBody, Charset responseCharset, ObjectMapper jsonMapper, XmlMapper xmlMapper) {
//         super(statusCode, statusText, responseHeaders, responseBody, responseCharset);
//         this.method = method;
//         this.url = url;
//         this.jsonMapper = jsonMapper;
//         this.xmlMapper = xmlMapper;
//     }
// 
//     public Errors getResponseBodyAsErrors() {
//         if (errors != null) {
//             return errors;
//         }
//         errors = parseResponseBody();
//         if (errors == null) {
//             return emptyErrors();
//         }
//         return errors;
//     }
// 
//     @Override
//     public String getMessage() {
//         return "An external HTTP request has failed: " + method + " " + url + " " + getStatusCode() + ". Response body: " + getResponseBodyAsString();
//     }
// 
//     protected Errors parseResponseBody() {
//         try {
//             if (hasContentType(APPLICATION_JSON)) {
//                 return jsonMapper.readValue(getResponseBodyAsString(), Errors.class);
//             }
//             if (hasContentType(APPLICATION_XML)) {
//                 return xmlMapper.readValue(getResponseBodyAsString(), Errors.class);
//             }
//             throw new IOException("Incompatible HTTP response " + CONTENT_TYPE + " header: " + getResponseHeaders().getContentType());
//         } catch (IOException e) {
//             log.warn("Cannot convert HTTP response body to {}: {}", Errors.class.getName(), e.getMessage());
//             return null;
//         }
//     }
// 
//     protected boolean hasContentType(MediaType mediaType) {
//         MediaType contentType = getResponseHeaders().getContentType();
//         return contentType != null && contentType.includes(mediaType);
//     }
// }


// Path: src/main/java/com/github/mkopylec/errorest/client/ErrorestTemplate.java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.github.mkopylec.errorest.exceptions.ExternalHttpRequestException;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.List;
import static org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.json;
import static org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.xml;

package com.github.mkopylec.errorest.client;




public class ErrorestTemplate extends RestTemplate {

    protected ObjectMapper jsonMapper = json().build();
    protected XmlMapper xmlMapper = xml().build();

    public ErrorestTemplate() {
        super();
    }

    public ErrorestTemplate(ClientHttpRequestFactory requestFactory) {
        super(requestFactory);
    }

    public ErrorestTemplate(List<HttpMessageConverter<?>> messageConverters) {
        super(messageConverters);
    }

    public void setJsonMapper(ObjectMapper jsonMapper) {
        this.jsonMapper = jsonMapper;
    }

    public void setXmlMapper(XmlMapper xmlMapper) {
        this.xmlMapper = xmlMapper;
    }

    @Override
    protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor) throws RestClientException {
        try {
            return super.doExecute(url, method, requestCallback, responseExtractor);
        } catch (HttpStatusCodeException ex) {
            throw createExternalHttpRequestException(method, url, ex);
        }
    }

    protected ExternalHttpRequestException createExternalHttpRequestException(HttpMethod method, URI url, HttpStatusCodeException ex) {