ApiException.java
package com.guinetik.rr.api;
import com.guinetik.rr.http.RocketRestException;
/**
* Exception thrown when an API request fails with rich error details.
*
* <p>This exception extends {@link RocketRestException} and provides additional
* context about API failures including the error message from the server.
* Use this when you need more details than the base exception provides.
*
* <h2>Exception Hierarchy</h2>
* <pre>
* RuntimeException
* └── RocketRestException (base HTTP exception)
* ├── CircuitBreakerOpenException
* ├── TokenExpiredException
* └── ApiException (richer error details)
* └── errorMessage: Server error message
* </pre>
*
* <h2>Handling ApiException</h2>
* <pre class="language-java">{@code
* try {
* User user = client.get("/users/999", User.class);
* } catch (ApiException e) {
* System.err.println("Status: " + e.getStatusCode());
* System.err.println("Message: " + e.getErrorMessage());
* System.err.println("Body: " + e.getResponseBody());
* } catch (RocketRestException e) {
* // Handles all other HTTP exceptions
* System.err.println("HTTP error: " + e.getStatusCode());
* }
* }</pre>
*
* <h2>Avoiding Exceptions with Result Pattern</h2>
* <p>Consider using the fluent API with {@link com.guinetik.rr.result.Result} to avoid exceptions:
* <pre class="language-java">{@code
* Result<User, ApiError> result = client.fluent().get("/users/999", User.class);
* result.match(
* user -> handleSuccess(user),
* error -> handleError(error) // No exception thrown
* );
* }</pre>
*
* @author guinetik <guinetik@gmail.com>
* @see RocketRestException
* @see com.guinetik.rr.result.Result
* @see com.guinetik.rr.result.ApiError
* @since 1.0.0
*/
public class ApiException extends RocketRestException {
private static final long serialVersionUID = 1L;
private final String errorMessage;
/**
* Creates a new ApiException with full error details.
*
* @param message The exception message
* @param responseBody The raw response body from the server
* @param errorMessage The parsed error message from the server
* @param statusCode The HTTP status code
*/
public ApiException(String message, String responseBody, String errorMessage, int statusCode) {
super(message, statusCode, responseBody);
this.errorMessage = errorMessage;
}
/**
* Creates a new ApiException with just a message.
*
* @param message The exception message
*/
public ApiException(String message) {
super(message);
this.errorMessage = null;
}
/**
* Creates a new ApiException with a message and cause.
*
* @param message The exception message
* @param cause The underlying cause
*/
public ApiException(String message, Throwable cause) {
super(message, cause);
this.errorMessage = null;
}
/**
* Gets the parsed error message from the server response.
* This is often a more user-friendly message extracted from the response body.
*
* @return The server error message, or null if not available
*/
public String getErrorMessage() {
return errorMessage;
}
}