From 5f2b31dc7f443ab9eb088d3150e2d4903cb40159 Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Sat, 7 Nov 2015 14:46:44 +0100 Subject: [PATCH] Reworked handling of error-responses from the Graph-API * The parsing of the response is done by the ObjectMapper from Jackson. * Unmapped exceptions are returned as such, instead of handing the handling to the parent. --- .../facebook/client/GraphApiErrorHandler.java | 123 ++++++++--------- .../exceptions/GraphApiException.java | 124 ++++++++++++++---- ...GraphApiExceptionJackson1Deserializer.java | 94 ------------- ...GraphApiExceptionJackson2Deserializer.java | 101 -------------- .../exceptions/GraphMethodException.java | 8 +- .../facebook/exceptions/OAuthException.java | 14 +- .../exceptions/PageMigratedException.java | 12 +- .../exceptions/RateExceededException.java | 8 +- .../exceptions/UnexpectedErrorException.java | 12 +- .../exceptions/UnknownErrorException.java | 12 +- .../exceptions/UnmappedErrorException.java | 17 +++ .../UnsupportedGetRequestException.java | 8 +- .../client/GraphApiErrorHandlerTest.java | 63 +++++++-- .../FacebookErrorMessageMappingTest.java | 20 +-- 14 files changed, 261 insertions(+), 355 deletions(-) delete mode 100644 src/main/java/de/juplo/facebook/exceptions/GraphApiExceptionJackson1Deserializer.java delete mode 100644 src/main/java/de/juplo/facebook/exceptions/GraphApiExceptionJackson2Deserializer.java create mode 100644 src/main/java/de/juplo/facebook/exceptions/UnmappedErrorException.java diff --git a/src/main/java/de/juplo/facebook/client/GraphApiErrorHandler.java b/src/main/java/de/juplo/facebook/client/GraphApiErrorHandler.java index faff55e..2b73e49 100644 --- a/src/main/java/de/juplo/facebook/client/GraphApiErrorHandler.java +++ b/src/main/java/de/juplo/facebook/client/GraphApiErrorHandler.java @@ -4,56 +4,48 @@ import de.juplo.facebook.exceptions.GraphApiException; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.List; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler; import org.springframework.util.FileCopyUtils; -import org.springframework.web.client.HttpMessageConverterExtractor; -import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.ResponseErrorHandler; /** + * Error-Handler for error-messages from the Facebook Graph-API. + *

+ * This error-handler handels responses withe the HTTP-status code + * {@code 4xx}. It tries to extract and parse the error-message + * from the HTTP-body. Successfully extracted and parsed messages are mapped + * to a hierarchy of exceptions, that reflects the hierarchy of the error- + * codes and -types. + *

+ * If the HTTP-status-code of the response is not {@code 4xx} or + * the HTTP-body could not be extracted or parsed, this error-handler + * delegates the handling to its parent. * - * @author kai + * @see Graph-API Documentation + * @see Inofficial Wiki For Facebook-Developers + * @author Kai Moritz */ -public class GraphApiErrorHandler extends OAuth2ErrorHandler +public class GraphApiErrorHandler implements ResponseErrorHandler { - private final OAuth2ErrorHandler errorHandler; - private List> messageConverters = - new RestTemplate().getMessageConverters(); + private final ResponseErrorHandler parent; - public GraphApiErrorHandler(OAuth2ErrorHandler errorHandler) + public GraphApiErrorHandler(ResponseErrorHandler errorHandler) { - super(null); - this.errorHandler = errorHandler; + this.parent = errorHandler; } - /** - * @param messageConverters the messageConverters to set - */ - @Override - public void setMessageConverters( - List> messageConverters - ) - { - this.messageConverters = messageConverters; - errorHandler.setMessageConverters(messageConverters); - } - @Override public boolean hasError(ClientHttpResponse response) throws IOException { return HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series()) - || this.errorHandler.hasError(response); + || this.parent.hasError(response); } @Override @@ -61,17 +53,36 @@ public class GraphApiErrorHandler extends OAuth2ErrorHandler { if (!HttpStatus.Series.CLIENT_ERROR.equals(response.getStatusCode().series())) { - // We should only care about 400 level errors. Ex: A 500 server error shouldn't - // be an oauth related error. - errorHandler.handleError(response); + // Let the parent-error-handler handle all errors, that are no client + // errors (4xx). + parent.handleError(response); + return; } - else + + + if (response.getBody() == null) { - // Need to use buffered response because input stream may need to be consumed multiple times. - ClientHttpResponse bufferedResponse = new ClientHttpResponse() - { - private byte[] lazyBody; + // There is no body to interpret in the HTTP-message + parent.handleError(response); + return; + } + + final byte[] body = FileCopyUtils.copyToByteArray(response.getBody()); + GraphApiException error; + + try + { + error = GraphApiException.create(body); + } + catch (Exception e) + { + // The body of the HTTP-message could not be parsed. + // Let the parent error-handler try to handle the response. + // To do so, we have to wrap the original response to fill in + // the buffered body, if needed + ClientHttpResponse buffered = new ClientHttpResponse() + { @Override public HttpStatus getStatusCode() throws IOException { @@ -81,16 +92,7 @@ public class GraphApiErrorHandler extends OAuth2ErrorHandler @Override public synchronized InputStream getBody() throws IOException { - if (lazyBody == null) { - InputStream bodyStream = response.getBody(); - if (bodyStream != null) { - lazyBody = FileCopyUtils.copyToByteArray(bodyStream); - } - else { - lazyBody = new byte[0]; - } - } - return new ByteArrayInputStream(lazyBody); + return new ByteArrayInputStream(body); } @Override @@ -118,31 +120,10 @@ public class GraphApiErrorHandler extends OAuth2ErrorHandler } }; - - HttpMessageConverterExtractor extractor = - new HttpMessageConverterExtractor<>( - GraphApiException.class, - messageConverters - ); - - try - { - GraphApiException body = extractor.extractData(bufferedResponse); - if (body != null) - { - // If we can get an OAuth2Exception already from the body, it is likely - // to have more information than the header does, so just re-throw it - // here. - body.setHttpErrorCode(response.getRawStatusCode()); - throw body; - } - } - catch (RestClientException|HttpMessageNotReadableException e) - { - // ignore - } - - errorHandler.handleError(bufferedResponse); + parent.handleError(buffered); + return; } + + throw error; } } diff --git a/src/main/java/de/juplo/facebook/exceptions/GraphApiException.java b/src/main/java/de/juplo/facebook/exceptions/GraphApiException.java index 1055b20..bd02565 100644 --- a/src/main/java/de/juplo/facebook/exceptions/GraphApiException.java +++ b/src/main/java/de/juplo/facebook/exceptions/GraphApiException.java @@ -3,6 +3,14 @@ package de.juplo.facebook.exceptions; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; import com.fasterxml.jackson.annotation.JsonRootName; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import java.io.IOException; +import java.io.InputStream; import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; /** @@ -10,64 +18,126 @@ import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; * * @author Kai Moritz */ -@org.codehaus.jackson.map.annotate.JsonDeserialize(using = GraphApiExceptionJackson1Deserializer.class) -@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = GraphApiExceptionJackson2Deserializer.class) public class GraphApiException extends OAuth2Exception { - private final String type; - private final int code; + final static ObjectMapper OBJECT_MAPPER; - private int httpErrorCode; + private final FacebookErrorMessage error; - public GraphApiException(String message, String type, int code) + static { - super(message); - this.type = type; - this.code = code; + OBJECT_MAPPER = new ObjectMapper(); + OBJECT_MAPPER.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); + OBJECT_MAPPER.configure(DeserializationFeature.ACCEPT_FLOAT_AS_INT, false); + OBJECT_MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, true); + } + + + public static GraphApiException create(InputStream in) + throws + IOException, + JsonParseException, + JsonMappingException + { + return create(OBJECT_MAPPER.readValue(in, FacebookErrorMessage.class)); + } + + public static GraphApiException create(byte[] message) + throws + IOException, + JsonParseException, + JsonMappingException + { + return create(OBJECT_MAPPER.readValue(message, FacebookErrorMessage.class)); + } + + public static GraphApiException create(FacebookErrorMessage error) + { + // see: http://fbdevwiki.com/wiki/Error_codes + switch(error.code) + { + // 1..99: general errors + case 1: return new UnknownErrorException(error); + case 2: return new UnexpectedErrorException(error); + case 21: return new PageMigratedException(error); + // 100..199: graph method errors + case 100: return new UnsupportedGetRequestException(error); + // 200..299: permission errors + // 300..399: data editing errors + // 400..449: authentication error + // 450..499: session errors + // 500..599: application messaging errors + // 600..699: FQL errors + case 613: return new RateExceededException(error); + // 700..749: ref errors + // 750..799: application integration errors + // 900..949: application information errors + // 950..999: batch api errors + // 1000..1099: event api errors + // 1100..1199: live-message errors + + default: return new UnmappedErrorException(error); + } + } + + + protected GraphApiException(FacebookErrorMessage error) + { + super(error.message); + this.error = error; } public String getType() { - return type; + return error.type; } - public int getCode() + public Integer getCode() { - return code; + return error.code; } - @Override - public int getHttpErrorCode() + public Integer getSubCode() { - return httpErrorCode == 0 ? super.getHttpErrorCode() : httpErrorCode; + return error.subCode; } - public void setHttpErrorCode(int httpErrorCode) + public String getUserTitle() { - this.httpErrorCode = httpErrorCode; + return error.userTitle; } + public String getUserMessage() + { + return error.userMessage; + } + + public String getTraceId() + { + return error.traceId; + } + + @Override public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("{error:{\"message\":\""); - builder.append(getMessage().replaceAll("\"", "\\\"")); - builder.append("\",\"type\":"); - builder.append(type.replaceAll("\"", "\\\"")); - builder.append("\",\"code\":"); - builder.append(code); - builder.append("}}"); - return builder.toString(); + try + { + return OBJECT_MAPPER.writeValueAsString(error); + } + catch(JsonProcessingException e) + { + return "Could not convert error in JSON-representation: " + e.getMessage(); + } } /** * This class represents an error message from the Graph-API * - * @see https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors + * @see Graph-API Documentation */ @JsonRootName("error") @JsonPropertyOrder({ "message", "type", "code", "error_subcode", "error_user_title", "error_user_msg", "fbtrace_id" }) diff --git a/src/main/java/de/juplo/facebook/exceptions/GraphApiExceptionJackson1Deserializer.java b/src/main/java/de/juplo/facebook/exceptions/GraphApiExceptionJackson1Deserializer.java deleted file mode 100644 index 165e7ce..0000000 --- a/src/main/java/de/juplo/facebook/exceptions/GraphApiExceptionJackson1Deserializer.java +++ /dev/null @@ -1,94 +0,0 @@ -package de.juplo.facebook.exceptions; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonProcessingException; -import org.codehaus.jackson.JsonToken; -import org.codehaus.jackson.map.DeserializationContext; -import org.codehaus.jackson.map.JsonDeserializer; - -/** - * @author Kai Moritz - */ -public class GraphApiExceptionJackson1Deserializer - extends - JsonDeserializer -{ - - @Override - public GraphApiException deserialize( - JsonParser jp, - DeserializationContext ctxt - ) - throws - IOException, - JsonProcessingException - { - JsonToken t = jp.getCurrentToken(); - if (t != JsonToken.START_OBJECT) - return null; - - t = jp.nextToken(); - if (t != JsonToken.FIELD_NAME) - return null; - - if (!jp.getCurrentName().equals("error")) - return null; - - t = jp.nextToken(); - if (t != JsonToken.START_OBJECT) - return null; - - String message = null, type = null; - Integer code = null; - - t = jp.nextToken(); - Map map = new HashMap<>(); - for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) - { - // Must point to field name - String fieldName = jp.getCurrentName(); - // And then the value... - t = jp.nextToken(); - - switch (t) - { - case VALUE_STRING: - switch(fieldName.toLowerCase()) - { - case "message": - message = jp.getText(); - break; - case "type": - type = jp.getText(); - break; - default: - return null; - } - break; - case VALUE_NUMBER_INT: - if (!fieldName.equalsIgnoreCase("code")) - return null; - code = jp.getValueAsInt(); - break; - default: - return null; - } - } - - if (message == null || type == null || code == null) - return null; - - switch (code) - { - case 1: return new UnknownErrorException(); - case 2: return new UnexpectedErrorException(); - case 21: return new PageMigratedException(message); - case 100: return new UnsupportedGetRequestException(); - case 613: return new RateExceededException(); - default: return new GraphApiException(message, type, code); - } - } -} diff --git a/src/main/java/de/juplo/facebook/exceptions/GraphApiExceptionJackson2Deserializer.java b/src/main/java/de/juplo/facebook/exceptions/GraphApiExceptionJackson2Deserializer.java deleted file mode 100644 index ea0e987..0000000 --- a/src/main/java/de/juplo/facebook/exceptions/GraphApiExceptionJackson2Deserializer.java +++ /dev/null @@ -1,101 +0,0 @@ -package de.juplo.facebook.exceptions; - - -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - - -/** - * @author Kai Moritz - * - */ -public class GraphApiExceptionJackson2Deserializer - extends - StdDeserializer -{ - public GraphApiExceptionJackson2Deserializer() - { - super(GraphApiException.class); - } - - @Override - public GraphApiException deserialize( - JsonParser jp, - DeserializationContext ctxt - ) - throws - IOException, - JsonProcessingException - { - JsonToken t = jp.getCurrentToken(); - if (t != JsonToken.START_OBJECT) - return null; - - t = jp.nextToken(); - if (t != JsonToken.FIELD_NAME) - return null; - - if (!jp.getCurrentName().equals("error")) - return null; - - t = jp.nextToken(); - if (t != JsonToken.START_OBJECT) - return null; - - String message = null, type = null; - Integer code = null; - - t = jp.nextToken(); - Map map = new HashMap<>(); - for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) - { - // Must point to field name - String fieldName = jp.getCurrentName(); - // And then the value... - t = jp.nextToken(); - - switch (t) - { - case VALUE_STRING: - switch(fieldName.toLowerCase()) - { - case "message": - message = jp.getText(); - break; - case "type": - type = jp.getText(); - break; - default: - return null; - } - break; - case VALUE_NUMBER_INT: - if (!fieldName.equalsIgnoreCase("code")) - return null; - code = jp.getValueAsInt(); - break; - default: - return null; - } - } - - if (message == null || type == null || code == null) - return null; - - switch (code) - { - case 1: return new UnknownErrorException(); - case 2: return new UnexpectedErrorException(); - case 21: return new PageMigratedException(message); - case 100: return new UnsupportedGetRequestException(); - case 613: return new RateExceededException(); - default: return new GraphApiException(message, type, code); - } - } -} diff --git a/src/main/java/de/juplo/facebook/exceptions/GraphMethodException.java b/src/main/java/de/juplo/facebook/exceptions/GraphMethodException.java index 21c56c5..7a8afc5 100644 --- a/src/main/java/de/juplo/facebook/exceptions/GraphMethodException.java +++ b/src/main/java/de/juplo/facebook/exceptions/GraphMethodException.java @@ -2,13 +2,13 @@ package de.juplo.facebook.exceptions; /** - * - * @author kai + * Baseclass for exceptions of type {@code GraphMethodException}. + * @author Kai Moritz */ public abstract class GraphMethodException extends GraphApiException { - public GraphMethodException(String message, int code) + GraphMethodException(FacebookErrorMessage error) { - super(message, "GraphMethodException", code); + super(error); } } diff --git a/src/main/java/de/juplo/facebook/exceptions/OAuthException.java b/src/main/java/de/juplo/facebook/exceptions/OAuthException.java index 4537720..e8fd312 100644 --- a/src/main/java/de/juplo/facebook/exceptions/OAuthException.java +++ b/src/main/java/de/juplo/facebook/exceptions/OAuthException.java @@ -1,14 +1,18 @@ package de.juplo.facebook.exceptions; +import de.juplo.facebook.exceptions.GraphApiException.FacebookErrorMessage; + + + /** - * - * @author kai + * Baseclass for exceptions of type {@code OAuthException}. + * @author Kai Moritz */ -public abstract class OAuthException extends GraphApiException +public class OAuthException extends GraphApiException { - public OAuthException(String message, int code) + protected OAuthException(FacebookErrorMessage error) { - super(message, "OAuthException", code); + super(error); } } diff --git a/src/main/java/de/juplo/facebook/exceptions/PageMigratedException.java b/src/main/java/de/juplo/facebook/exceptions/PageMigratedException.java index d327b6d..dfa76cf 100644 --- a/src/main/java/de/juplo/facebook/exceptions/PageMigratedException.java +++ b/src/main/java/de/juplo/facebook/exceptions/PageMigratedException.java @@ -7,8 +7,8 @@ import java.util.regex.Pattern; /** - * - * @author kai + * 21: Page ID (XXX) was migrated to page ID (YYY). + * @author Kai Moritz */ public class PageMigratedException extends OAuthException { @@ -18,12 +18,12 @@ public class PageMigratedException extends OAuthException private final Long oldId, newId; - public PageMigratedException(String message) + protected PageMigratedException(FacebookErrorMessage error) { - super(message, 21); - Matcher matcher = pattern.matcher(message); + super(error); + Matcher matcher = pattern.matcher(error.message); if (!matcher.find()) - throw new RuntimeException("Could not parse migration-error: " + message); + throw new RuntimeException("Could not parse migration-error: " + error.message); oldId = Long.parseLong(matcher.group(1)); newId = Long.parseLong(matcher.group(2)); } diff --git a/src/main/java/de/juplo/facebook/exceptions/RateExceededException.java b/src/main/java/de/juplo/facebook/exceptions/RateExceededException.java index cdda586..adc0b4a 100644 --- a/src/main/java/de/juplo/facebook/exceptions/RateExceededException.java +++ b/src/main/java/de/juplo/facebook/exceptions/RateExceededException.java @@ -2,13 +2,13 @@ package de.juplo.facebook.exceptions; /** - * - * @author kai + * 613: Calls to stream have exceeded the rate of 600 calls per 600 seconds. + * @author Kai Moritz */ public class RateExceededException extends OAuthException { - public RateExceededException() + protected RateExceededException(FacebookErrorMessage error) { - super("(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.", 613); + super(error); } } diff --git a/src/main/java/de/juplo/facebook/exceptions/UnexpectedErrorException.java b/src/main/java/de/juplo/facebook/exceptions/UnexpectedErrorException.java index 5aefff6..6d7369b 100644 --- a/src/main/java/de/juplo/facebook/exceptions/UnexpectedErrorException.java +++ b/src/main/java/de/juplo/facebook/exceptions/UnexpectedErrorException.java @@ -1,14 +1,18 @@ package de.juplo.facebook.exceptions; +import de.juplo.facebook.exceptions.GraphApiException.FacebookErrorMessage; + + + /** - * - * @author kai + * 2: An unexpected error has occurred. + * @author Kai Moritz */ public class UnexpectedErrorException extends OAuthException { - public UnexpectedErrorException() + protected UnexpectedErrorException(FacebookErrorMessage error) { - super("An unexpected error has occurred. Please retry your request later.", 2); + super(error); } } diff --git a/src/main/java/de/juplo/facebook/exceptions/UnknownErrorException.java b/src/main/java/de/juplo/facebook/exceptions/UnknownErrorException.java index 6e336f4..c281f09 100644 --- a/src/main/java/de/juplo/facebook/exceptions/UnknownErrorException.java +++ b/src/main/java/de/juplo/facebook/exceptions/UnknownErrorException.java @@ -1,14 +1,18 @@ package de.juplo.facebook.exceptions; +import de.juplo.facebook.exceptions.GraphApiException.FacebookErrorMessage; + + + /** - * - * @author kai + * 1: An unknown error has occurred. + * @author Kai Moritz */ public class UnknownErrorException extends OAuthException { - public UnknownErrorException() + protected UnknownErrorException(FacebookErrorMessage error) { - super("An unknown error has occurred.", 1); + super(error); } } diff --git a/src/main/java/de/juplo/facebook/exceptions/UnmappedErrorException.java b/src/main/java/de/juplo/facebook/exceptions/UnmappedErrorException.java new file mode 100644 index 0000000..2ed9b95 --- /dev/null +++ b/src/main/java/de/juplo/facebook/exceptions/UnmappedErrorException.java @@ -0,0 +1,17 @@ +package de.juplo.facebook.exceptions; + + +/** + * Marker class for error-messages, that are not mapped yet. + * Pleas help us to complete the list of possible errors and report errors, + * that are mapped to this class to info@juplo.de. Thanxs! + * + * @author Kai Moritz + */ +public class UnmappedErrorException extends GraphApiException +{ + protected UnmappedErrorException(FacebookErrorMessage error) + { + super(error); + } +} diff --git a/src/main/java/de/juplo/facebook/exceptions/UnsupportedGetRequestException.java b/src/main/java/de/juplo/facebook/exceptions/UnsupportedGetRequestException.java index 1d5b44d..6905808 100644 --- a/src/main/java/de/juplo/facebook/exceptions/UnsupportedGetRequestException.java +++ b/src/main/java/de/juplo/facebook/exceptions/UnsupportedGetRequestException.java @@ -2,13 +2,13 @@ package de.juplo.facebook.exceptions; /** - * - * @author kai + * 100: Unsupported get request. + * @author Kai Moritz */ public class UnsupportedGetRequestException extends GraphMethodException { - public UnsupportedGetRequestException() + protected UnsupportedGetRequestException(FacebookErrorMessage error) { - super("Unsupported get request.", 100); + super(error); } } diff --git a/src/test/java/de/juplo/facebook/client/GraphApiErrorHandlerTest.java b/src/test/java/de/juplo/facebook/client/GraphApiErrorHandlerTest.java index ddd19a6..15dfba3 100644 --- a/src/test/java/de/juplo/facebook/client/GraphApiErrorHandlerTest.java +++ b/src/test/java/de/juplo/facebook/client/GraphApiErrorHandlerTest.java @@ -6,6 +6,7 @@ import de.juplo.facebook.exceptions.RateExceededException; import de.juplo.facebook.exceptions.GraphApiException; import de.juplo.facebook.exceptions.UnknownErrorException; import de.juplo.facebook.exceptions.PageMigratedException; +import de.juplo.facebook.exceptions.UnmappedErrorException; import java.util.Date; import java.util.Map; import java.util.Set; @@ -79,7 +80,7 @@ public class GraphApiErrorHandlerTest { log.debug("{}", e.toString()); assertEquals("invalid_request", e.getOAuth2ErrorCode()); - assertEquals(1, e.getCode()); + assertEquals(new Integer(1), e.getCode()); assertEquals("An unknown error has occurred.", e.getMessage()); assertEquals("OAuthException", e.getType()); } @@ -110,7 +111,7 @@ public class GraphApiErrorHandlerTest { log.debug("{}", e.toString()); assertEquals("invalid_request", e.getOAuth2ErrorCode()); - assertEquals(2, e.getCode()); + assertEquals(new Integer(2), e.getCode()); assertEquals("An unexpected error has occurred. Please retry your request later.", e.getMessage()); assertEquals("OAuthException", e.getType()); } @@ -141,7 +142,7 @@ public class GraphApiErrorHandlerTest { log.debug("{}", e.toString()); assertEquals("invalid_request", e.getOAuth2ErrorCode()); - assertEquals(21, e.getCode()); + assertEquals(new Integer(21), e.getCode()); assertEquals("(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603. Please update your API calls to the new ID", e.getMessage()); assertEquals("OAuthException", e.getType()); } @@ -172,7 +173,7 @@ public class GraphApiErrorHandlerTest { log.debug("{}", e.toString()); assertEquals("invalid_request", e.getOAuth2ErrorCode()); - assertEquals(100, e.getCode()); + assertEquals(new Integer(100), e.getCode()); assertEquals("Unsupported get request.", e.getMessage()); assertEquals("GraphMethodException", e.getType()); } @@ -203,7 +204,7 @@ public class GraphApiErrorHandlerTest { log.debug("{}", e.toString()); assertEquals("invalid_request", e.getOAuth2ErrorCode()); - assertEquals(613, e.getCode()); + assertEquals(new Integer(613), e.getCode()); assertEquals("(#613) Calls to stream have exceeded the rate of 600 calls per 600 seconds.", e.getMessage()); assertEquals("OAuthException", e.getType()); } @@ -234,16 +235,16 @@ public class GraphApiErrorHandlerTest { log.debug("{}", e.toString()); assertEquals("invalid_request", e.getOAuth2ErrorCode()); - assertEquals(999999999, e.getCode()); + assertEquals(new Integer(999999999), e.getCode()); assertEquals("This error does not exist.", e.getMessage()); assertEquals("NonexistentException", e.getType()); } } @Test - public void testInvlalidErrors() + public void testUnmappedErrors() { - log.info("testInvalidErrors"); + log.info("testUnmappedErrors"); requestFactory.setBody( @@ -261,9 +262,16 @@ public class GraphApiErrorHandlerTest clientTemplate.getForObject("ANY", SOME.class); fail("The expected exception was not thrown"); } - catch(HttpClientErrorException e) + catch(UnmappedErrorException e) { log.debug("{}", e.toString()); + assertNull(e.getMessage()); + assertEquals("Whatever", e.getType()); + assertEquals(new Integer(999999999), e.getCode()); + assertNull(e.getSubCode()); + assertNull(e.getUserTitle()); + assertNull(e.getUserMessage()); + assertNull(e.getTraceId()); } catch(Exception e) { @@ -285,9 +293,16 @@ public class GraphApiErrorHandlerTest clientTemplate.getForObject("ANY", SOME.class); fail("The expected exception was not thrown"); } - catch(HttpClientErrorException e) + catch(UnmappedErrorException e) { log.debug("{}", e.toString()); + assertNull(e.getMessage()); + assertEquals("Whatever", e.getType()); + assertEquals(new Integer(999999999), e.getCode()); + assertNull(e.getSubCode()); + assertNull(e.getUserTitle()); + assertNull(e.getUserMessage()); + assertNull(e.getTraceId()); } catch(Exception e) { @@ -299,7 +314,7 @@ public class GraphApiErrorHandlerTest "{\n" + " \"error\":\n" + " {\n" + - " \"message\": \"Not a Graph-Api-Exception.\",\n" + + " \"message\": \"An unmapped Graph-API-Exception.\",\n" + " \"type\": null,\n" + " \"code\": 999999999\n" + " }\n" + @@ -310,9 +325,16 @@ public class GraphApiErrorHandlerTest clientTemplate.getForObject("ANY", SOME.class); fail("The expected exception was not thrown"); } - catch(HttpClientErrorException e) + catch(UnmappedErrorException e) { log.debug("{}", e.toString()); + assertEquals("An unmapped Graph-API-Exception.", e.getMessage()); + assertNull(e.getType()); + assertEquals(new Integer(999999999), e.getCode()); + assertNull(e.getSubCode()); + assertNull(e.getUserTitle()); + assertNull(e.getUserMessage()); + assertNull(e.getTraceId()); } catch(Exception e) { @@ -324,7 +346,7 @@ public class GraphApiErrorHandlerTest "{\n" + " \"error\":\n" + " {\n" + - " \"message\": \"Not a Graph-Api-Exception.\",\n" + + " \"message\": \"An unmapped Graph-API-Exception.\",\n" + " \"code\": 999999999\n" + " }\n" + "}"); @@ -334,14 +356,27 @@ public class GraphApiErrorHandlerTest clientTemplate.getForObject("ANY", SOME.class); fail("The expected exception was not thrown"); } - catch(HttpClientErrorException e) + catch(UnmappedErrorException e) { log.debug("{}", e.toString()); + assertEquals("An unmapped Graph-API-Exception.", e.getMessage()); + assertNull(e.getType()); + assertEquals(new Integer(999999999), e.getCode()); + assertNull(e.getSubCode()); + assertNull(e.getUserTitle()); + assertNull(e.getUserMessage()); + assertNull(e.getTraceId()); } catch(Exception e) { fail("A wrong exception was thrown: " + e.toString()); } + } + + @Test + public void testInvlalidErrors() + { + log.info("testInvalidErrors"); requestFactory.setBody( diff --git a/src/test/java/de/juplo/facebook/exceptions/FacebookErrorMessageMappingTest.java b/src/test/java/de/juplo/facebook/exceptions/FacebookErrorMessageMappingTest.java index cd1a4c8..cb25662 100644 --- a/src/test/java/de/juplo/facebook/exceptions/FacebookErrorMessageMappingTest.java +++ b/src/test/java/de/juplo/facebook/exceptions/FacebookErrorMessageMappingTest.java @@ -1,12 +1,9 @@ package de.juplo.facebook.exceptions; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.SerializationFeature; import de.juplo.facebook.exceptions.GraphApiException.FacebookErrorMessage; +import static de.juplo.facebook.exceptions.GraphApiException.OBJECT_MAPPER; import java.io.IOException; -import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -28,17 +25,6 @@ public class FacebookErrorMessageMappingTest "}" + "}"; - ObjectMapper mapper; - - - @Before - public void setUp() - { - mapper = new ObjectMapper(); - mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); - mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true); - } - @Test public void testSerialize() throws JsonProcessingException @@ -52,14 +38,14 @@ public class FacebookErrorMessageMappingTest error.userMessage = "A message"; error.traceId = "EJplcsCHuLu"; - assertEquals(example, mapper.writeValueAsString(error)); + assertEquals(example, OBJECT_MAPPER.writeValueAsString(error)); } @Test public void testDeserialize() throws IOException { FacebookErrorMessage error = - mapper.readValue(example, FacebookErrorMessage.class); + OBJECT_MAPPER.readValue(example, FacebookErrorMessage.class); assertEquals("Message describing the error", error.message); assertEquals("OAuthException", error.type); -- 2.20.1