package org.gbif.ws.client;

import com.google.common.io.CharStreams;
import feign.Response;
import feign.codec.ErrorDecoder;
import org.gbif.api.exception.ServiceUnavailableException;
import org.gbif.ws.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;

import javax.validation.ValidationException;
import java.io.IOException;
import java.io.Reader;
import java.net.URI;

@SuppressWarnings("UnstableApiUsage")
public class ClientErrorDecoder implements ErrorDecoder {

  private static final Logger LOG = LoggerFactory.getLogger(ClientErrorDecoder.class);

  @Override
  public Exception decode(String methodKey, Response response) {
    String message = null;

    try (Reader reader = response.body().asReader()) {
      //Easy way to read the stream and get a String object
      message = CharStreams.toString(reader);
      LOG.error("Client exception: {}", message);
    } catch (IOException e) {
      LOG.error("Exception during reading client error response", e);
    }

    switch (response.status()) {
      case 400:
        return new IllegalArgumentException("A bad request received");
      case 401:
        return new AccessDeniedException("Unauthorized request received");
      case 403:
        return new AccessDeniedException("Forbidden request received");
      case 404:
        return new NotFoundException("Resource not found", URI.create(response.request().url()));
      case 422:
        return message != null
            ? new ValidationException(extractValidationErrorMessage(message))
            : new ValidationException();
      case 500:
        return new ServiceUnavailableException("An internal server error occurred, please try again later");
      case 501:
        return new UnsupportedOperationException(message != null ? message : "Method not implement yet");
      default:
        return new RuntimeException(message != null ? message : "Unexpected exception");
    }
  }

  private String extractValidationErrorMessage(String message) {
    return message.replace("<ul><li>", "")
        .replace("</li></ul>", "")
        .replace("<li></li>", ", ");
  }
}

@@ -748,16 +748,53 @@
  null;%0A%0A
+    if (response.body() != null) %7B%0A  
     try 
@@ -836,24 +836,26 @@
 Reader()) %7B%0A
+  
       //Easy
@@ -908,16 +908,18 @@
 t%0A      
+  
 message 
@@ -952,24 +952,26 @@
 der);%0A      
+ 
+ 
 LOG.error(%22C
@@ -1006,16 +1006,18 @@
 e);%0A    
+  
 %7D catch 
@@ -1036,24 +1036,26 @@
  e) %7B%0A      
+ 
+ 
 LOG.error(%22E
@@ -1102,24 +1102,32 @@
 ponse%22, e);%0A
+      %7D%0A
     %7D%0A%0A    s

Fix NPE in ClientErrorDecoder