* 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.
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.
+ * <p>
+ * 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.
+ * <p>
+ * 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 <a href="https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors">Graph-API Documentation</a>
+ * @see <a href="http://fbdevwiki.com/wiki/Error_codes">Inofficial Wiki For Facebook-Developers</a>
+ * @author Kai Moritz
*/
-public class GraphApiErrorHandler extends OAuth2ErrorHandler
+public class GraphApiErrorHandler implements ResponseErrorHandler
{
- private final OAuth2ErrorHandler errorHandler;
- private List<HttpMessageConverter<?>> 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<HttpMessageConverter<?>> 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
{
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
{
@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
}
};
-
- HttpMessageConverterExtractor<GraphApiException> 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;
}
}
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;
/**
*
* @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 <a href="https://developers.facebook.com/docs/graph-api/using-graph-api/v2.5#errors">Graph-API Documentation</a>
*/
@JsonRootName("error")
@JsonPropertyOrder({ "message", "type", "code", "error_subcode", "error_user_title", "error_user_msg", "fbtrace_id" })
+++ /dev/null
-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<GraphApiException>
-{
-
- @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<String, String> 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);
- }
- }
-}
+++ /dev/null
-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<GraphApiException>
-{
- 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<String, String> 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);
- }
- }
-}
/**
- *
- * @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);
}
}
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);
}
}
/**
- *
- * @author kai
+ * 21: Page ID (XXX) was migrated to page ID (YYY).
+ * @author Kai Moritz
*/
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));
}
/**
- *
- * @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);
}
}
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);
}
}
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);
}
}
--- /dev/null
+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);
+ }
+}
/**
- *
- * @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);
}
}
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;
{
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());
}
{
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());
}
{
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());
}
{
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());
}
{
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());
}
{
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(
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)
{
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)
{
"{\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" +
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)
{
"{\n" +
" \"error\":\n" +
" {\n" +
- " \"message\": \"Not a Graph-Api-Exception.\",\n" +
+ " \"message\": \"An unmapped Graph-API-Exception.\",\n" +
" \"code\": 999999999\n" +
" }\n" +
"}");
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(
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;
"}" +
"}";
- 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
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);