1 package de.juplo.facebook.errors;
4 import com.fasterxml.jackson.core.JsonProcessingException;
5 import com.fasterxml.jackson.databind.DeserializationFeature;
6 import com.fasterxml.jackson.databind.ObjectMapper;
7 import com.fasterxml.jackson.databind.SerializationFeature;
8 import java.io.ByteArrayInputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13 import org.springframework.core.io.buffer.DataBufferUtils;
14 import org.springframework.http.HttpHeaders;
15 import org.springframework.http.HttpStatus;
16 import org.springframework.web.reactive.function.BodyExtractors;
17 import org.springframework.web.reactive.function.client.ClientResponse;
18 import reactor.core.publisher.Mono;
23 * Base exception for Facebook Graph-Api exceptions.
27 public class GraphApiException extends RuntimeException
29 public enum Type { OAuthException, GraphMethodException }
32 final static Logger LOG = LoggerFactory.getLogger(GraphApiException.class);
33 final static ObjectMapper OBJECT_MAPPER;
35 public final HttpStatus status;
36 public final HttpHeaders headers;
37 public final FacebookErrorMessage error;
42 OBJECT_MAPPER = new ObjectMapper();
43 OBJECT_MAPPER.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
44 OBJECT_MAPPER.configure(DeserializationFeature.ACCEPT_FLOAT_AS_INT, false);
45 OBJECT_MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
50 public static Mono<GraphApiException> create(ClientResponse response)
52 return DataBufferUtils.join(response.body(BodyExtractors.toDataBuffers()))
54 byte[] bytes = new byte[dataBuffer.readableByteCount()];
55 dataBuffer.read(bytes);
56 DataBufferUtils.release(dataBuffer);
59 .defaultIfEmpty(new byte[0])
60 .map(bytes -> create(response.statusCode(), response.headers().asHttpHeaders(), bytes));
63 public static GraphApiException create(
71 return create(status, headers, OBJECT_MAPPER.readValue(in, FacebookErrorMessage.class));
73 catch (IOException | RuntimeException e)
75 return new ErrorResponseParsingErrorException(status, headers, e);
79 public static GraphApiException create(
85 return create(status, headers, new ByteArrayInputStream(message));
88 public static GraphApiException create(
91 FacebookErrorMessage error
94 // see: http://fbdevwiki.com/wiki/Error_codes
97 // 1..99: general errors
98 case 1: return new UnknownErrorException(status, headers, error);
99 case 2: return new UnexpectedErrorException(status, headers, error);
100 case 4: return new ApplicationRequestLimitReachedException(status, headers, error);
101 case 10: return new AuthorizationMissingException(status, headers, error);
102 case 12: return new DeprecatedException(status, headers, error);
103 case 17: return new AccountRequestLimitReachedException(status, headers, error);
104 case 21: return new PageMigratedException(status, headers, error);
105 case 32: return new PageRequestLimitReachedException(status, headers, error);
106 // 100..199: graph method errors
107 case 100: return new UnsupportedGetRequestException(status, headers, error);
108 case 102: return new UserAccessTokenRequiredException(status, headers, error);
109 case 104: return new AccessTokenRequiredException(status, headers, error);
110 case 190: return new AccessTokenExpiredException(status, headers, error);
111 // 200..299: permission errors
112 case 200: return new ApplicationNotAuthorizedByUserException(status, headers, error);
211 case 299: return new AuthorizationMissingException(status, headers, error);
212 // 200..299: permission errors
213 // 300..399: data editing errors ?
214 case 341: return new TemporaryRateLimitExceededException(status, headers, error);
215 // 400..449: authentication error
216 // 450..499: session errors
217 // 500..599: application messaging errors ?
218 case 506: return new MultipleConcurrentPostsException(status, headers, error);
219 // 600..699: FQL errors
220 case 613: return new RateLimitExceededException(status, headers, error);
221 // 700..749: ref errors
222 // 750..799: application integration errors
223 // 900..949: application information errors
224 // 950..999: batch api errors
225 // 1000..1099: event api errors
226 // 1100..1199: live-message errors
227 case 1609005: return new LinkPostFailureException(status, headers, error);
228 case 2200: return new CallbackVerificationFailedException(status, headers, error);
231 GraphApiException e = new UnmappedErrorException(status, headers, error);
232 LOG.info("unmapped error: {}", e.toString());
238 protected GraphApiException(
241 FacebookErrorMessage error
244 super(error.message);
245 this.status = status;
246 this.headers = headers;
251 public HttpStatus getStatus()
256 public HttpHeaders getHeaders()
261 public Type getType()
263 return error.type == null ? null : Type.valueOf(error.type);
266 public Integer getCode()
271 public Integer getSubCode()
273 return error.subCode;
276 public String getUserTitle()
278 return error.userTitle;
281 public String getUserMessage()
283 return error.userMessage;
286 public String getTraceId()
288 return error.traceId;
293 public String toString()
297 return OBJECT_MAPPER.writeValueAsString(error);
299 catch(JsonProcessingException e)
301 // This should never happen. But in case of a mistake: be verbose!
302 LOG.error("could not convert message into JSON: {}", e);
303 return e.getMessage();