All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.nike.backstopper.exception.ApiException Maven / Gradle / Ivy

There is a newer version: 2.0.1
Show newest version
package com.nike.backstopper.exception;

import com.nike.backstopper.apierror.ApiError;
import com.nike.internal.util.Pair;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import static java.util.Collections.singletonList;

/**
 * Generic API RuntimeException to explicitly invoke the error handling system. Most of the time you'll want to create
 * an instance using the {@link ApiException.Builder}, e.g.
 * {@code
 * ApiException.newBuilder().withApiErrors(SOME_ERROR, OTHER_ERROR).withExceptionMessage("super useful message").build()}.
 * The builder has many options that directly affect the response and what is logged, so take a close look at the
 * available methods.
 *
 * @author Nic Munroe
 */
public class ApiException extends RuntimeException {

    /**
     * The {@link ApiError}s associated with this instance. Will never be null or empty.
     */
    private final List apiErrors;
    /**
     * Any extra details you want logged when this error is handled. Will never be null, but might be empty.
     * NOTE: This will always be a mutable list so it can be modified at any time.
     */
    private final List> extraDetailsForLogging;

    /**
     * Handles the simple common case where you just want to throw a single {@link ApiError} and nothing else.
     */
    public ApiException(ApiError error) {
        super();
        if (error == null)
            throw new IllegalArgumentException("error cannot be null");
        this.apiErrors = new ArrayList<>(singletonList(error));
        this.extraDetailsForLogging = new ArrayList<>();
    }

    /**
     * Creates an instance on top of {@link Exception#Exception(String)} super constructor. You can safely pass in null
     * for message if you have no message. If another exception caused this to be thrown then you'll want
     * {@link #ApiException(List, List, String, Throwable)} instead so that the proper super constructor is used.
     *
     * 

NOTE: Most of the time you wouldn't want to use this constructor directly - use the * {@link ApiException.Builder} instead. */ public ApiException(List apiErrors, List> extraDetailsForLogging, String message) { super(message); if (apiErrors == null || apiErrors.isEmpty()) throw new IllegalArgumentException("apiErrors cannot be null or empty"); if (extraDetailsForLogging == null) extraDetailsForLogging = new ArrayList<>(); this.apiErrors = new ArrayList<>(apiErrors); this.extraDetailsForLogging = new ArrayList<>(extraDetailsForLogging); } /** * Creates an instance on top of {@link Exception#Exception(String, Throwable)} super constructor. You can safely * pass in null for message if you have no message. If another exception did *not* cause this to be thrown then * you'll want {@link #ApiException(List, List, String)} instead so that the proper super constructor is used. * *

NOTE: Most of the time you wouldn't want to use this constructor directly - use the * {@link ApiException.Builder} instead. */ public ApiException(List apiErrors, List> extraDetailsForLogging, String message, Throwable cause) { super(message, cause); if (apiErrors == null || apiErrors.isEmpty()) throw new IllegalArgumentException("apiErrors cannot be null or empty"); if (extraDetailsForLogging == null) extraDetailsForLogging = new ArrayList<>(); this.apiErrors = new ArrayList<>(apiErrors); this.extraDetailsForLogging = new ArrayList<>(extraDetailsForLogging); } /** * Shortcut for calling {@link ApiException.Builder#newBuilder()} directly. */ public static Builder newBuilder() { return Builder.newBuilder(); } /** * The {@link ApiError}s associated with this instance. Will never be null or empty. */ public List getApiErrors() { return apiErrors; } /** * Any extra details you want logged when this error is handled. Will never be null, but might be empty. */ public List> getExtraDetailsForLogging() { return extraDetailsForLogging; } /** * Builder for {@link ApiException}. */ @SuppressWarnings("WeakerAccess") public static class Builder { private List apiErrors = new ArrayList<>(); private List> extraDetailsForLogging = new ArrayList<>(); private String message; private Throwable cause; public Builder() {} public static Builder newBuilder() { return new Builder(); } /** * Adds the given errors to what will ultimately become {@link ApiException#apiErrors}. */ public Builder withApiErrors(Collection apiErrors) { this.apiErrors.addAll(apiErrors); return this; } /** * Adds the given errors to what will ultimately become {@link ApiException#apiErrors}. */ public Builder withApiErrors(ApiError... apiErrors) { return withApiErrors(Arrays.asList(apiErrors)); } /** * Adds the given logging details to what will ultimately become {@link ApiException#extraDetailsForLogging}. */ public Builder withExtraDetailsForLogging(Collection> extraDetailsForLogging) { this.extraDetailsForLogging.addAll(extraDetailsForLogging); return this; } /** * Adds the given logging details to what will ultimately become {@link ApiException#extraDetailsForLogging}. */ @SafeVarargs public final Builder withExtraDetailsForLogging(Pair... extraDetailsForLogging) { return withExtraDetailsForLogging(Arrays.asList(extraDetailsForLogging)); } /** * The given message will be used as part of the {@link Exception#Exception(String)} or * {@link Exception#Exception(String, Throwable)} super constructor. Could be used as context for what went * wrong if the API Errors aren't self explanatory. */ public Builder withExceptionMessage(String message) { this.message = message; return this; } /** * The given throwable will be applied to the {@link Exception#Exception(String, Throwable)} super constructor. * If another error caused this {@link ApiException} in the first place then you should definitely include it * here so it can be logged and help with debugging the issue. */ public Builder withExceptionCause(Throwable cause) { this.cause = cause; return this; } /** * Creates the {@link ApiException} from the data this builder contains. */ public ApiException build() { if (this.cause == null) return new ApiException(apiErrors, extraDetailsForLogging, message); else return new ApiException(apiErrors, extraDetailsForLogging, message, cause); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy