001/* 002 * Copyright (c) 2010-2024 Mark Allen, Norbert Bartels. 003 * 004 * Permission is hereby granted, free of charge, to any person obtaining a copy 005 * of this software and associated documentation files (the "Software"), to deal 006 * in the Software without restriction, including without limitation the rights 007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 008 * copies of the Software, and to permit persons to whom the Software is 009 * furnished to do so, subject to the following conditions: 010 * 011 * The above copyright notice and this permission notice shall be included in 012 * all copies or substantial portions of the Software. 013 * 014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 020 * THE SOFTWARE. 021 */ 022package com.restfb.exception; 023 024import static java.lang.String.format; 025 026import java.util.Optional; 027 028import com.restfb.json.JsonObject; 029 030/** 031 * Indicates that the Facebook Graph API endpoint returned JSON which indicates an error condition. 032 * <p> 033 * Example:<code> 034 { 035 "error": { 036 "type": "Exception", 037 "message": "...", 038 "code": 210, 039 "error_subcode": 123, 040 "error_user_title": "A title", 041 "error_user_msg": "A message" 042 } 043 } </code> 044 * 045 * @author <a href="http://restfb.com">Mark Allen</a> 046 * @since 1.5 047 */ 048public class FacebookGraphException extends FacebookErrorMessageException { 049 private static final long serialVersionUID = 1L; 050 051 /** 052 * The Facebook Graph API error type. 053 */ 054 private final String errorType; 055 056 /** 057 * The Facebook API error message. 058 */ 059 private final String errorMessage; 060 061 /** 062 * The Facebook API error user title. 063 */ 064 private final String errorUserTitle; 065 066 /** 067 * The Facebook API error user message. 068 */ 069 private final String errorUserMessage; 070 071 /** 072 * The Facebook API error code. 073 */ 074 private final Integer errorCode; 075 076 /** 077 * The Facebook API error subcode. 078 */ 079 private final Integer errorSubcode; 080 081 /** 082 * The HTTP status code returned by the server. 083 */ 084 private final Integer httpStatusCode; 085 086 private final Boolean isTransient; 087 088 /** 089 * Creates an exception with the given error type and message. 090 * 091 * @param errorType 092 * Value of the Facebook response attribute {@code error.type}. 093 * @param errorMessage 094 * Value of the Facebook response attribute {@code error.message}. 095 * @param errorCode 096 * Value of the Facebook response attribute {@code error.code}. 097 * @param errorSubcode 098 * Value of the Facebook response attribute {@code error.error_subcode}. 099 * @param httpStatusCode 100 * The HTTP status code returned by the server, e.g. 500. 101 * @param errorUserTitle 102 * Value of the Facebook response attribute {@code error.error_user_title}. 103 * @param errorUserMessage 104 * Value of the Facebook response attribute {@code error.error_user_msg}. 105 * @param isTransient 106 * 107 */ 108 public FacebookGraphException(String errorType, String errorMessage, Integer errorCode, Integer errorSubcode, 109 Integer httpStatusCode, String errorUserTitle, String errorUserMessage, Boolean isTransient, 110 JsonObject rawError) { 111 super(format("Received Facebook error response of type %s: %s (code %s, subcode %s) '%s - %s'", errorType, 112 errorMessage, errorCode, errorSubcode, errorUserTitle, errorUserMessage)); 113 this.errorType = errorType; 114 this.errorMessage = errorMessage; 115 this.errorCode = errorCode; 116 this.errorSubcode = errorSubcode; 117 this.httpStatusCode = httpStatusCode; 118 this.errorUserTitle = errorUserTitle; 119 this.errorUserMessage = errorUserMessage; 120 this.isTransient = isTransient; 121 setRawErrorJson(rawError); 122 } 123 124 /** 125 * Gets the Facebook Graph API error type. 126 * 127 * @return The Facebook Graph API error type. 128 */ 129 public String getErrorType() { 130 return errorType; 131 } 132 133 /** 134 * Gets the Facebook Graph API error message. 135 * 136 * @return The Facebook Graph API error message. 137 */ 138 public String getErrorMessage() { 139 return errorMessage; 140 } 141 142 /** 143 * Gets the Facebook API error code. 144 * 145 * @return The Facebook API error code. 146 */ 147 public Integer getErrorCode() { 148 return errorCode; 149 } 150 151 /** 152 * Gets the Facebook API error subcode. 153 * 154 * @return The Facebook API error subcode. 155 */ 156 public Integer getErrorSubcode() { 157 return errorSubcode; 158 } 159 160 /** 161 * Gets the HTTP status code returned by the server. 162 * 163 * @return The HTTP status code returned by the server. 164 * @since 1.6.10 165 */ 166 public Integer getHttpStatusCode() { 167 return httpStatusCode; 168 } 169 170 /** 171 * Gets the Facebook API error user title. 172 * 173 * @return the Facebook API error user title 174 * @since 1.7.1 175 */ 176 public String getErrorUserTitle() { 177 return errorUserTitle; 178 } 179 180 /** 181 * Gets the Facebook API error user message. 182 * 183 * @return the Facebook API error user message 184 * @since 1.7.1 185 */ 186 public String getErrorUserMessage() { 187 return errorUserMessage; 188 } 189 190 public Boolean getIsTransient() { 191 return isTransient; 192 } 193 194 /** 195 * Gets the Facebook API error {@code fbtrace_id}. 196 * 197 * Internal support identifier. When reporting a bug related to a Graph API call, include the fbtrace_id to help us 198 * find log data for debugging. 199 * 200 * @return the Facebook API error {@code fbtrace_id} 201 */ 202 public String getFbtraceId() { 203 if (getRawErrorJson() != null && getRawErrorJson().get("error").isObject()) { 204 JsonObject errorJson = getRawErrorJson().get("error").asObject(); 205 return errorJson.getString("fbtrace_id", ""); 206 } 207 208 return ""; 209 } 210 211 /** 212 * returns the error data as defined <a href="https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes/">here</a> as JsonObject. 213 * We use no special object to be future proof and allow other error JSONs to use this. 214 * @return Optional<JsonObject> with the JsonObject 215 */ 216 public Optional<JsonObject> getErrorData() { 217 if (getRawErrorJson() != null && getRawErrorJson().get("error").isObject()) { 218 JsonObject errorJson = getRawErrorJson().get("error").asObject(); 219 if (errorJson.contains("error_data")) { 220 return Optional.of(errorJson.get("error_data").asObject()); 221 } 222 } 223 224 return Optional.empty(); 225 } 226 227 /** 228 * special method to get the String result to the given field of the error_data field 229 * @param field field you like to fetch 230 * @return String with the result or empty String if not available 231 */ 232 public String getErrorData(String field) { 233 Optional<JsonObject> errorDataOpt = getErrorData(); 234 if (errorDataOpt.isPresent()) { 235 return errorDataOpt.get().getString(field, ""); 236 } 237 238 return ""; 239 } 240}