Skip to content

Add additional error information #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 12 additions & 60 deletions src/main/java/com/ibm/cloud/sdk/core/service/WatsonService.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
*/
package com.ibm.cloud.sdk.core.service;

import com.google.gson.JsonObject;
import com.ibm.cloud.sdk.core.http.HttpClientSingleton;
import com.ibm.cloud.sdk.core.http.HttpConfigOptions;
import com.ibm.cloud.sdk.core.http.HttpHeaders;
Expand All @@ -39,8 +38,6 @@
import com.ibm.cloud.sdk.core.util.CredentialUtils;
import com.ibm.cloud.sdk.core.util.RequestUtils;
import com.ibm.cloud.sdk.core.util.ResponseConverterUtils;
import com.ibm.cloud.sdk.core.util.ResponseUtils;

import jersey.repackaged.jsr166e.CompletableFuture;
import okhttp3.Call;
import okhttp3.Callback;
Expand All @@ -54,7 +51,6 @@

import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;

Expand All @@ -68,8 +64,6 @@ public abstract class WatsonService {
private static final String URL = "url";
private static final String PATH_AUTHORIZATION_V1_TOKEN = "/v1/token";
private static final String AUTHORIZATION = "authorization";
private static final String MESSAGE_ERROR_3 = "message";
private static final String MESSAGE_ERROR_2 = "error_message";
private static final String BASIC = "Basic ";
private static final String BEARER = "Bearer ";
private static final String APIKEY_AS_USERNAME = "apikey";
Expand Down Expand Up @@ -98,8 +92,6 @@ public abstract class WatsonService {
/** The Constant MESSAGE_CODE. */
protected static final String MESSAGE_CODE = "code";

/** The Constant MESSAGE_ERROR. */
protected static final String MESSAGE_ERROR = "error";

/** The Constant VERSION. */
protected static final String VERSION = "version";
Expand Down Expand Up @@ -308,38 +300,6 @@ public boolean isTokenManagerSet() {
return tokenManager != null;
}

/**
* Gets the error message from a JSON response.
*
* <pre>
* {
* code: 400
* error: 'bad request'
* }
* </pre>
*
* @param response the HTTP response
* @return the error message from the JSON object
*/
private String getErrorMessage(Response response) {
String error = ResponseUtils.getString(response);
try {

final JsonObject jsonObject = ResponseUtils.getJsonObject(error);
if (jsonObject.has(MESSAGE_ERROR)) {
error = jsonObject.get(MESSAGE_ERROR).getAsString();
} else if (jsonObject.has(MESSAGE_ERROR_2)) {
error = jsonObject.get(MESSAGE_ERROR_2).getAsString();
} else if (jsonObject.has(MESSAGE_ERROR_3)) {
error = jsonObject.get(MESSAGE_ERROR_3).getAsString();
}
} catch (final Exception e) {
// Ignore any kind of exception parsing the json and use fallback String version of response
}

return error;
}

/**
* Gets the name.
*
Expand Down Expand Up @@ -494,39 +454,31 @@ protected <T> T processServiceCall(final ResponseConverter<T> converter, final R
return converter.convert(response);
}

// There was a Client Error 4xx or a Server Error 5xx
// Get the error message and create the exception
final String error = getErrorMessage(response);
LOG.log(Level.SEVERE, response.request().method() + " " + response.request().url().toString() + ", status: "
+ response.code() + ", error: " + error);

switch (response.code()) {
case HttpStatus.BAD_REQUEST: // HTTP 400
throw new BadRequestException(error != null ? error : "Bad Request", response);
throw new BadRequestException(response);
case HttpStatus.UNAUTHORIZED: // HTTP 401
throw new UnauthorizedException("Unauthorized: Access is denied due to invalid credentials. "
+ "Tip: Did you set the Endpoint?", response);
throw new UnauthorizedException(response);
case HttpStatus.FORBIDDEN: // HTTP 403
throw new ForbiddenException(error != null ? error : "Forbidden: Service refuse the request", response);
throw new ForbiddenException(response);
case HttpStatus.NOT_FOUND: // HTTP 404
throw new NotFoundException(error != null ? error : "Not found", response);
throw new NotFoundException(response);
case HttpStatus.NOT_ACCEPTABLE: // HTTP 406
throw new ForbiddenException(error != null ? error : "Forbidden: Service refuse the request", response);
throw new ForbiddenException(response);
case HttpStatus.CONFLICT: // HTTP 409
throw new ConflictException(error != null ? error : "", response);
throw new ConflictException(response);
case HttpStatus.REQUEST_TOO_LONG: // HTTP 413
throw new RequestTooLargeException(error != null ? error
: "Request too large: " + "The request entity is larger than the server is able to process", response);
throw new RequestTooLargeException(response);
case HttpStatus.UNSUPPORTED_MEDIA_TYPE: // HTTP 415
throw new UnsupportedException(error != null ? error : "Unsupported Media Type", response);
throw new UnsupportedException(response);
case HttpStatus.TOO_MANY_REQUESTS: // HTTP 429
throw new TooManyRequestsException(error != null ? error : "Too many requests", response);
throw new TooManyRequestsException(response);
case HttpStatus.INTERNAL_SERVER_ERROR: // HTTP 500
throw new InternalServerErrorException(error != null ? error : "Internal Server Error", response);
throw new InternalServerErrorException(response);
case HttpStatus.SERVICE_UNAVAILABLE: // HTTP 503
throw new ServiceUnavailableException(error != null ? error : "Service Unavailable", response);
throw new ServiceUnavailableException(response);
default: // other errors
throw new ServiceResponseException(response.code(), error, response);
throw new ServiceResponseException(response.code(), response);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ public class BadRequestException extends ServiceResponseException {
/**
* Instantiates a new BadRequest Exception. HTTP 400
*
* @param message the error message
* @param response the HTTP response
*/
public BadRequestException(String message, Response response) {
super(HttpStatus.BAD_REQUEST, message, response);
public BadRequestException(Response response) {
super(HttpStatus.BAD_REQUEST, response);
if (this.getMessage() == null) {
this.setMessage("Bad request");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public class ConflictException extends ServiceResponseException {
/**
* Instantiates a new Forbidden Exception.
*
* @param message the error message
* @param response the HTTP response
*/
public ConflictException(String message, Response response) {
super(HttpStatus.CONFLICT, message, response);
public ConflictException(Response response) {
super(HttpStatus.CONFLICT, response);
if (this.getMessage() == null) {
this.setMessage("");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public class ForbiddenException extends ServiceResponseException {
/**
* Instantiates a new Forbidden Exception.
*
* @param message the error message
* @param response the HTTP response
*/
public ForbiddenException(String message, Response response) {
super(HttpStatus.FORBIDDEN, message, response);
public ForbiddenException(Response response) {
super(HttpStatus.FORBIDDEN, response);
if (this.getMessage() == null) {
this.setMessage("Forbidden: Service refused the request");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public class InternalServerErrorException extends ServiceResponseException {
/**
* Instantiates a new Internal Server Error Exception.
*
* @param message the error message
* @param response the HTTP response
*/
public InternalServerErrorException(String message, Response response) {
super(HttpStatus.INTERNAL_SERVER_ERROR, message, response);
public InternalServerErrorException(Response response) {
super(HttpStatus.INTERNAL_SERVER_ERROR, response);
if (this.getMessage() == null) {
this.setMessage("Internal server error");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public class NotFoundException extends ServiceResponseException {
/**
* Instantiates a new not found exception.
*
* @param message the message
* @param response the HTTP response
*/
public NotFoundException(String message, Response response) {
super(HttpStatus.NOT_FOUND, message, response);
public NotFoundException(Response response) {
super(HttpStatus.NOT_FOUND, response);
if (this.getMessage() == null) {
this.setMessage("Not found");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public class RequestTooLargeException extends ServiceResponseException {
/**
* Instantiates a new Request Too Large Exception.
*
* @param message the error message
* @param response the HTTP response
*/
public RequestTooLargeException(String message, Response response) {
super(HttpStatus.REQUEST_TOO_LONG, message, response);
public RequestTooLargeException(Response response) {
super(HttpStatus.REQUEST_TOO_LONG, response);
if (this.getMessage() == null) {
this.setMessage("Request too large: The request entity is larger than the server is able to process");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@
*/
package com.ibm.cloud.sdk.core.service.exception;

import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.ibm.cloud.sdk.core.http.Headers;
import com.ibm.cloud.sdk.core.util.GsonSingleton;
import com.ibm.cloud.sdk.core.util.ResponseUtils;
import okhttp3.Response;

import java.lang.reflect.Type;
import java.util.Map;

/**
* Generic Service Response Exception.
*/
Expand All @@ -22,23 +30,46 @@ public class ServiceResponseException extends RuntimeException {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;

/** Potential error message keys. */
private static final String MESSAGE_ERROR = "error";
private static final String MESSAGE_ERROR_2 = "error_message";
private static final String MESSAGE_ERROR_3 = "message";
private static final String[] ERROR_KEYS = { MESSAGE_ERROR, MESSAGE_ERROR_2, MESSAGE_ERROR_3 };

private static final Type debuggingInfoType = new TypeToken<Map<String, Object>>() { }.getType();

/** The status code. */
private final int statusCode;

/** The HTTP response. */
private final Response response;
private String message;
private Headers headers;
private Map<String, Object> debuggingInfo;

/**
* Instantiates a new Service Response Exception.
*
* @param statusCode the status code
* @param message the error message
* @param response the HTTP response
*/
public ServiceResponseException(int statusCode, String message, Response response) {
super(message);
public ServiceResponseException(int statusCode, Response response) {
super();
this.statusCode = statusCode;
this.response = response;
this.headers = new Headers(response.headers());

String responseString = ResponseUtils.getString(response);
try {
final JsonObject jsonObject = ResponseUtils.getJsonObject(responseString);
for (String errorKey : ERROR_KEYS) {
if (jsonObject.has(errorKey)) {
this.message = jsonObject.remove(errorKey).getAsString();
break;
}
}
this.debuggingInfo = GsonSingleton.getGson().fromJson(jsonObject, debuggingInfoType);
} catch (final Exception e) {
// Ignore any kind of exception parsing the json and use fallback String version of response
this.message = responseString;
}
}

/**
Expand All @@ -51,11 +82,38 @@ public int getStatusCode() {
}

/**
* Gets the HTTP response.
* Gets the error message.
*
* @return the error message
*/
public String getMessage() {
return message;
}

/**
* Sets the error message.
*
* @param message the error message
*/
protected void setMessage(String message) {
this.message = message;
}

/**
* Gets the headers.
*
* @return the headers
*/
public Headers getHeaders() {
return headers;
}

/**
* Gets the response information other than the error message.
*
* @return the HTTP response
* @return the response information other than the error message
*/
public Response getResponse() {
return response;
public Map<String, Object> getDebuggingInfo() {
return debuggingInfo;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public class ServiceUnavailableException extends ServiceResponseException {
/**
* Instantiates a new Service Unavailable Exception.
*
* @param message the error message
* @param response the HTTP response
*/
public ServiceUnavailableException(String message, Response response) {
super(HttpStatus.SERVICE_UNAVAILABLE, message, response);
public ServiceUnavailableException(Response response) {
super(HttpStatus.SERVICE_UNAVAILABLE, response);
if (this.getMessage() == null) {
this.setMessage("Service unavailable");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@ public class TooManyRequestsException extends ServiceResponseException {
/**
* Instantiates a new Too Many Requests Exception.
*
* @param message the error message
* @param response the HTTP response
*/
public TooManyRequestsException(String message, Response response) {
super(TOO_MANY_REQUESTS, message, response);
public TooManyRequestsException(Response response) {
super(TOO_MANY_REQUESTS, response);
if (this.getMessage() == null) {
this.setMessage("Too many requests");
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ public class UnauthorizedException extends ServiceResponseException {
/**
* Instantiates a new Unauthorized Exception.
*
* @param message the error message
* @param response the HTTP response
*/
public UnauthorizedException(String message, Response response) {
super(HttpStatus.UNAUTHORIZED, message, response);
public UnauthorizedException(Response response) {
super(HttpStatus.UNAUTHORIZED, response);
if (this.getMessage() == null) {
this.setMessage("Unauthorized: Access is denied due to invalid credentials. Tip: Did you set the endpoint?");
}
}

}
Loading