Java Code Examples for com.nike.backstopper.apierror.ApiError#getHttpStatusCode()

The following examples show how to use com.nike.backstopper.apierror.ApiError#getHttpStatusCode() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 6 votes vote down vote up
@Test
public void allErrorsShouldBeCoreApiErrorsOrCoreApiErrorWrappersOrFallInProjectSpecificErrorRange() {
    ProjectSpecificErrorCodeRange projectSpecificErrorCodeRange = getProjectApiErrors().getProjectSpecificErrorCodeRange();

    for (ApiError error : getProjectApiErrors().getProjectApiErrors()) {
        boolean valid = false;
        if (getProjectApiErrors().getCoreApiErrors().contains(error) || getProjectApiErrors().isWrapperAroundCoreError(error, getProjectApiErrors().getCoreApiErrors()))
            valid = true;
        else if (projectSpecificErrorCodeRange != null && projectSpecificErrorCodeRange.isInRange(error))
            valid = true;

        if (!valid) {
            throw new AssertionError("Found an ApiError in the ProjectApiErrors that is not a core error or wrapper around a core error, and its error code does not fall in the  " +
                                     "range of getProjectApiErrors().getProjectSpecificErrorCodeRange(). getProjectApiErrors().getProjectSpecificErrorCodeRange(): " + projectSpecificErrorCodeRange +
                                     ". Offending error info: name=" + error.getName() + ", errorCode=" + error.getErrorCode() + ", message=\"" + error.getMessage() + "\", httpStatusCode=" +
                                     error.getHttpStatusCode() + ", class=" + error.getClass().getName());
        }
    }
}
 
Example 2
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 6 votes vote down vote up
@Test
public void allErrorsShouldBeCoreApiErrorsOrCoreApiErrorWrappersOrFallInProjectSpecificErrorRange() {
    ProjectSpecificErrorCodeRange projectSpecificErrorCodeRange =
        getProjectApiErrors().getProjectSpecificErrorCodeRange();

    for (ApiError error : getProjectApiErrors().getProjectApiErrors()) {
        boolean valid = false;
        if (getProjectApiErrors().getCoreApiErrors().contains(error) || getProjectApiErrors()
            .isWrapperAroundCoreError(error, getProjectApiErrors().getCoreApiErrors()))
            valid = true;
        else if (projectSpecificErrorCodeRange != null && projectSpecificErrorCodeRange.isInRange(error))
            valid = true;

        if (!valid) {
            throw new AssertionError(
                "Found an ApiError in the ProjectApiErrors that is not a core error or wrapper around a core error, and its error code does not fall in the  "
                +
                "range of getProjectApiErrors().getProjectSpecificErrorCodeRange(). getProjectApiErrors().getProjectSpecificErrorCodeRange(): "
                + projectSpecificErrorCodeRange +
                ". Offending error info: name=" + error.getName() + ", errorCode=" + error.getErrorCode()
                + ", message=\"" + error.getMessage() + "\", httpStatusCode=" +
                error.getHttpStatusCode() + ", class=" + error.getClass().getName());
        }
    }
}
 
Example 3
Source File: Jersey1UnhandledExceptionHandlerTest.java    From backstopper with Apache License 2.0 6 votes vote down vote up
@Test
public void generateLastDitchFallbackErrorResponseInfo_returns_expected_value() {
    // given
    Exception ex = new Exception("kaboom");
    RequestInfoForLogging reqMock = mock(RequestInfoForLogging.class);
    String errorId = UUID.randomUUID().toString();
    Map<String, List<String>> headersMap = MapBuilder.builder("error_uid", singletonList(errorId)).build();

    ApiError expectedGenericError = testProjectApiErrors.getGenericServiceError();
    int expectedHttpStatusCode = expectedGenericError.getHttpStatusCode();
    Map<String, List<String>> expectedHeadersMap = new HashMap<>(headersMap);
    String expectedBodyPayload = JsonUtilWithDefaultErrorContractDTOSupport.writeValueAsString(
        new DefaultErrorContractDTO(errorId, singletonList(expectedGenericError))
    );

    // when
    ErrorResponseInfo<Response.ResponseBuilder> response = handler.generateLastDitchFallbackErrorResponseInfo(ex, reqMock, errorId, headersMap);

    // then
    assertThat(response.httpStatusCode).isEqualTo(expectedHttpStatusCode);
    assertThat(response.headersToAddToResponse).isEqualTo(expectedHeadersMap);
    Response builtFrameworkResponse = response.frameworkRepresentationObj.build();
    assertThat(builtFrameworkResponse.getStatus()).isEqualTo(expectedHttpStatusCode);
    assertThat(builtFrameworkResponse.getEntity()).isEqualTo(expectedBodyPayload);
}
 
Example 4
Source File: JaxRsUnhandledExceptionHandlerTest.java    From backstopper with Apache License 2.0 6 votes vote down vote up
@Test
public void generateLastDitchFallbackErrorResponseInfo_returns_expected_value() {
    // given
    Exception ex = new Exception("kaboom");
    RequestInfoForLogging reqMock = mock(RequestInfoForLogging.class);
    String errorId = UUID.randomUUID().toString();
    Map<String, List<String>> headersMap = MapBuilder.builder("error_uid", singletonList(errorId)).build();

    ApiError expectedGenericError = testProjectApiErrors.getGenericServiceError();
    int expectedHttpStatusCode = expectedGenericError.getHttpStatusCode();
    Map<String, List<String>> expectedHeadersMap = new HashMap<>(headersMap);
    String expectedBodyPayload = JsonUtilWithDefaultErrorContractDTOSupport.writeValueAsString(
        new DefaultErrorContractDTO(errorId, singletonList(expectedGenericError))
    );

    // when
    ErrorResponseInfo<Response.ResponseBuilder> response = handler.generateLastDitchFallbackErrorResponseInfo(ex, reqMock, errorId, headersMap);

    // then
    assertThat(response.httpStatusCode).isEqualTo(expectedHttpStatusCode);
    assertThat(response.headersToAddToResponse).isEqualTo(expectedHeadersMap);
    Response builtFrameworkResponse = response.frameworkRepresentationObj.build();
    assertThat(builtFrameworkResponse.getStatus()).isEqualTo(expectedHttpStatusCode);
    assertThat(builtFrameworkResponse.getEntity()).isEqualTo(expectedBodyPayload);
}
 
Example 5
Source File: ProjectApiErrors.java    From backstopper with Apache License 2.0 6 votes vote down vote up
/**
 * @return true if the given {@link ApiError} is a "wrapper" around one of the given core errors, false otherwise. A
 *          "wrapper" means it shares the same client-facing properties; its {@link ApiError#getErrorCode()},
 *          {@link ApiError#getMessage()}, and {@link ApiError#getHttpStatusCode()} must exactly match one of the
 *          core error instances. The {@link ApiError#getName()} and {@link ApiError#getMetadata()} do not have to
 *          match.
 */
protected boolean isWrapperAroundCoreError(ApiError projectError, List<ApiError> coreErrors) {
    if (projectError == null) {
        return false;
    }

    for (ApiError coreApiError : coreErrors) {
        boolean errorCodeMatches = Objects.equals(projectError.getErrorCode(), coreApiError.getErrorCode());
        boolean messageMatches = Objects.equals(projectError.getMessage(), coreApiError.getMessage());
        boolean httpStatusCodeMatches = coreApiError.getHttpStatusCode() == projectError.getHttpStatusCode();
        if (errorCodeMatches && messageMatches && httpStatusCodeMatches) {
            return true;
        }
    }

    return false;
}
 
Example 6
Source File: ProjectApiErrors.java    From backstopper with Apache License 2.0 6 votes vote down vote up
/**
 * @return The {@code fullList} passed in after it has been filtered to only contain {@link ApiError}s with the
 *          given {@code filterHttpStatusCode}. This will return an empty list if either argument is null (or if
 *          there are no errors in the list that match the filter). It will never return null. NOTE: This method
 *          uses a for loop to run through the given {@code fullList}, so if the collection you pass in does not
 *          have a defined order (e.g. a Set), then the returned list's order is undefined. If the collection you
 *          pass in has a defined order, then the output list will be in the same order minus any items that are
 *          removed.
 */
public List<ApiError> getSublistContainingOnlyHttpStatusCode(Collection<ApiError> fullList,
                                                             Integer filterHttpStatusCode) {
    if (fullList == null || filterHttpStatusCode == null) {
        return Collections.emptyList();
    }

    List<ApiError> filteredList = new ArrayList<>();
    for (ApiError ae : fullList) {
        if (ae.getHttpStatusCode() == filterHttpStatusCode) {
            filteredList.add(ae);
        }
    }

    return filteredList;
}
 
Example 7
Source File: ApiExceptionHandlerBaseTest.java    From backstopper with Apache License 2.0 5 votes vote down vote up
private List<ApiError> findAllApiErrorsWithHttpStatusCode(int httpStatusCode) {
    List<ApiError> returnList = new ArrayList<>();
    for (ApiError error : testProjectApiErrors.getProjectApiErrors()) {
        if (error.getHttpStatusCode() == httpStatusCode)
            returnList.add(error);
    }
    return returnList;
}
 
Example 8
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 5 votes vote down vote up
protected ApiError findRandomApiErrorWithHttpStatusCode(int httpStatusCode) {
    for (ApiError error : getProjectApiErrors().getProjectApiErrors()) {
        if (error.getHttpStatusCode() == httpStatusCode)
            return error;
    }
    throw new IllegalStateException("Couldn't find ApiError with HTTP status code: " + httpStatusCode);
}
 
Example 9
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 5 votes vote down vote up
@Test
public void verifyGetStatusCodePriorityOrderMethodContainsAllRelevantCodes() {
    for (ApiError error : getProjectApiErrors().getProjectApiErrors()) {
        int relevantCode = error.getHttpStatusCode();
        boolean containsRelevantCode = getProjectApiErrors().getStatusCodePriorityOrder().contains(relevantCode);
        if (!containsRelevantCode)
            throw new AssertionError("getStatusCodePriorityOrder() did not contain HTTP Status Code: " + relevantCode + " for " + getProjectApiErrors().getClass().getName() + "'s ApiError: " + error);
    }
}
 
Example 10
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 5 votes vote down vote up
@Test
public void verifyErrorsAreInRangeShouldNotThrowExceptionIfListIncludesCoreApiErrorWrapper() {
    ApiError coreApiError = BarebonesCoreApiErrorForTesting.GENERIC_SERVICE_ERROR;
    final ApiError coreApiErrorWrapper = new ApiErrorBase("blah", coreApiError.getErrorCode(), coreApiError.getMessage(), coreApiError.getHttpStatusCode());
    ProjectApiErrors pae = ProjectApiErrorsForTesting.withProjectSpecificData(Collections.singletonList(coreApiErrorWrapper), null);

    assertThat(pae, notNullValue());
    assertThat(pae.getProjectApiErrors().contains(coreApiErrorWrapper), is(true));
}
 
Example 11
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 5 votes vote down vote up
private boolean areWrappersOfEachOther(ApiError error1, ApiError error2) {
    boolean errorCodeMatches = Objects.equals(error1.getErrorCode(), error2.getErrorCode());
    boolean messageMatches = Objects.equals(error1.getMessage(), error2.getMessage());
    boolean httpStatusCodeMatches = error1.getHttpStatusCode() == error2.getHttpStatusCode();
    if (errorCodeMatches && messageMatches && httpStatusCodeMatches) {
        return true;
    }

    return false;
}
 
Example 12
Source File: ApiErrorUtil.java    From backstopper with Apache License 2.0 5 votes vote down vote up
/**
 * Method for checking equality of two {@link ApiError}. This can be used in implementations of {@link ApiError}
 */
public static boolean isApiErrorEqual(ApiError apiError, Object o) {
    if (apiError == o) return true;
    if (apiError == null) return false;
    if (o == null || !(o instanceof ApiError)) return false;
    ApiError that = (ApiError) o;
    return apiError.getHttpStatusCode() == that.getHttpStatusCode() &&
            Objects.equals(apiError.getName(), that.getName()) &&
            Objects.equals(apiError.getErrorCode(), that.getErrorCode()) &&
            Objects.equals(apiError.getMessage(), that.getMessage()) &&
            Objects.equals(apiError.getMetadata(), that.getMetadata());
}
 
Example 13
Source File: SpringUnhandledExceptionHandlerTest.java    From backstopper with Apache License 2.0 5 votes vote down vote up
@Test
public void generateLastDitchFallbackErrorResponseInfo_returns_expected_value() throws JsonProcessingException {
    // given
    Exception ex = new Exception("kaboom");
    RequestInfoForLogging reqMock = mock(RequestInfoForLogging.class);
    String errorId = UUID.randomUUID().toString();
    Map<String, List<String>> headersMap = MapBuilder.builder("error_uid", singletonList(errorId)).build();

    ApiError expectedGenericError = testProjectApiErrors.getGenericServiceError();
    int expectedHttpStatusCode = expectedGenericError.getHttpStatusCode();
    Map<String, List<String>> expectedHeadersMap = new HashMap<>(headersMap);
    String expectedBodyPayload = JsonUtilWithDefaultErrorContractDTOSupport.writeValueAsString(
        new DefaultErrorContractDTO(errorId, singletonList(expectedGenericError))
    );

    // when
    ErrorResponseInfo<ModelAndView> response = handlerSpy
        .generateLastDitchFallbackErrorResponseInfo(ex, reqMock, errorId, headersMap);

    // then
    assertThat(response.httpStatusCode).isEqualTo(expectedHttpStatusCode);
    assertThat(response.headersToAddToResponse).isEqualTo(expectedHeadersMap);
    assertThat(response.frameworkRepresentationObj.getView()).isInstanceOf(MappingJackson2JsonView.class);
    ObjectMapper objectMapperUsed = ((MappingJackson2JsonView)response.frameworkRepresentationObj.getView()).getObjectMapper();
    assertThat(objectMapperUsed).isSameAs(JsonUtilWithDefaultErrorContractDTOSupport.DEFAULT_SMART_MAPPER);
    assertThat(response.frameworkRepresentationObj.getModel()).hasSize(1);
    Object modelObj = response.frameworkRepresentationObj.getModel().values().iterator().next();
    assertThat(modelObj).isInstanceOf(DefaultErrorContractDTO.class);
    assertThat(objectMapperUsed.writeValueAsString(modelObj)).isEqualTo(expectedBodyPayload);
}
 
Example 14
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 5 votes vote down vote up
protected ApiError findRandomApiErrorWithHttpStatusCode(int httpStatusCode) {
    for (ApiError error : getProjectApiErrors().getProjectApiErrors()) {
        if (error.getHttpStatusCode() == httpStatusCode)
            return error;
    }
    throw new IllegalStateException("Couldn't find ApiError with HTTP status code: " + httpStatusCode);
}
 
Example 15
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 5 votes vote down vote up
@Test
public void verifyGetStatusCodePriorityOrderMethodContainsAllRelevantCodes() {
    for (ApiError error : getProjectApiErrors().getProjectApiErrors()) {
        int relevantCode = error.getHttpStatusCode();
        boolean containsRelevantCode = getProjectApiErrors().getStatusCodePriorityOrder().contains(relevantCode);
        if (!containsRelevantCode) {
            throw new AssertionError(
                "getStatusCodePriorityOrder() did not contain HTTP Status Code: " + relevantCode + " for "
                + getProjectApiErrors().getClass().getName() + "'s ApiError: " + error
            );
        }
    }
}
 
Example 16
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 5 votes vote down vote up
@Test
public void verifyErrorsAreInRangeShouldNotThrowExceptionIfListIncludesCoreApiErrorWrapper() {
    ApiError coreApiError = BarebonesCoreApiErrorForTesting.GENERIC_SERVICE_ERROR;
    final ApiError coreApiErrorWrapper =
        new ApiErrorBase("blah", coreApiError.getErrorCode(), coreApiError.getMessage(),
                         coreApiError.getHttpStatusCode());
    ProjectApiErrors pae =
        ProjectApiErrorsForTesting.withProjectSpecificData(Collections.singletonList(coreApiErrorWrapper), null);

    assertThat(pae, notNullValue());
    assertThat(pae.getProjectApiErrors().contains(coreApiErrorWrapper), is(true));
}
 
Example 17
Source File: ProjectApiErrorsTestBase.java    From backstopper with Apache License 2.0 5 votes vote down vote up
private boolean areWrappersOfEachOther(ApiError error1, ApiError error2) {
    boolean errorCodeMatches = Objects.equals(error1.getErrorCode(), error2.getErrorCode());
    boolean messageMatches = Objects.equals(error1.getMessage(), error2.getMessage());
    boolean httpStatusCodeMatches = error1.getHttpStatusCode() == error2.getHttpStatusCode();
    //noinspection RedundantIfStatement
    if (errorCodeMatches && messageMatches && httpStatusCodeMatches) {
        return true;
    }

    return false;
}
 
Example 18
Source File: ApiExceptionHandlerBase.java    From backstopper with Apache License 2.0 4 votes vote down vote up
/**
 * Helper method for {@link #maybeHandleException(Throwable, RequestInfoForLogging)} that handles the nitty gritty
 * of logging the appropriate request info, converting the errors into an {@link DefaultErrorContractDTO}, and using
 * {@link #prepareFrameworkRepresentation(DefaultErrorContractDTO, int, Collection, Throwable,
 * RequestInfoForLogging)} to generate the appropriate response for the client.
 *  @param clientErrors The ApiErrors that the originalException converted into.
 * @param extraDetailsForLogging Any extra details that should be logged along with the usual request/error info.
 * @param extraResponseHeaders Any extra response headers that should be sent to the caller in the HTTP response.
 * @param originalException The original exception that we are handling.
 * @param request The incoming request.
 */
protected ErrorResponseInfo<T> doHandleApiException(
  SortedApiErrorSet clientErrors, List<Pair<String, String>> extraDetailsForLogging,
  List<Pair<String, List<String>>> extraResponseHeaders, Throwable originalException,
  RequestInfoForLogging request
) {
    Throwable coreException = unwrapAndFindCoreException(originalException);

    // Add connection type to our extra logging data if appropriate. This particular log message is here so it can
    //      be done in one spot rather than trying to track down all the different places we're handling
    //      NetworkExceptionBase subclasses (and possibly missing some by accident).
    if (coreException instanceof NetworkExceptionBase) {
        NetworkExceptionBase neb = ((NetworkExceptionBase)coreException);
        extraDetailsForLogging.add(Pair.of("connection_type", neb.getConnectionType()));
    }

    // We may need to drop some of our client errors if we have a mix of http status codes (see javadocs on
    //      ProjectApiError's determineHighestPriorityHttpStatusCode and getSublistContainingOnlyHttpStatusCode
    //      methods).
    Integer highestPriorityStatusCode = projectApiErrors.determineHighestPriorityHttpStatusCode(clientErrors);
    Collection<ApiError> filteredClientErrors =
        projectApiErrors.getSublistContainingOnlyHttpStatusCode(clientErrors, highestPriorityStatusCode);

    // Bulletproof against somehow getting a completely empty collection of client errors. This should never happen
    //      but if it does we want a reasonable response.
    if (filteredClientErrors == null || filteredClientErrors.size() == 0) {
        ApiError genericServiceError = projectApiErrors.getGenericServiceError();
        UUID trackingUuid = UUID.randomUUID();
        String trackingLogKey = "bad_handler_logic_tracking_uuid";
        extraDetailsForLogging.add(Pair.of(trackingLogKey, trackingUuid.toString()));
        logger.error(String.format(
            "Found a situation where we ended up with 0 ApiErrors to return to the client. This should not happen "
            + "and likely indicates a logic error in ApiExceptionHandlerBase, or a ProjectApiErrors that isn't "
            + "setup properly. Defaulting to " + genericServiceError.getName() + " for now, but this should be "
            + "investigated and fixed. Search for %s=%s in the logs to find the log message that contains the "
            + "details of the request along with the full stack trace of the original exception. "
            + "unfiltered_api_errors=%s",
            trackingLogKey, trackingUuid.toString(), utils.concatenateErrorCollection(clientErrors)
        ));
        filteredClientErrors = Collections.singletonList(genericServiceError);
        highestPriorityStatusCode = genericServiceError.getHttpStatusCode();
    }

    // Log all the relevant error/debugging info.
    StringBuilder logMessage = new StringBuilder();
    logMessage.append("ApiExceptionHandlerBase handled exception occurred: ");
    String errorId = utils.buildErrorMessageForLogs(
        logMessage, request, filteredClientErrors, highestPriorityStatusCode, coreException, extraDetailsForLogging
    );

    // Don't log the stack trace on 4xx validation exceptions, but do log it on anything else.
    if (shouldLogStackTrace(
        highestPriorityStatusCode, filteredClientErrors, originalException, coreException, request
    )) {
        logger.error(logMessage.toString(), originalException);
    }
    else {
        logger.warn(logMessage.toString());
    }

    // Generate our internal default representation of the error contract (the DefaultErrorContractDTO), and
    //      translate it into the representation required by the framework.
    DefaultErrorContractDTO errorContractDTO = new DefaultErrorContractDTO(errorId, filteredClientErrors);
    T frameworkRepresentation = prepareFrameworkRepresentation(
        errorContractDTO, highestPriorityStatusCode, filteredClientErrors, originalException, request
    );

    // Setup the final additional response headers that should be sent back to the caller.
    Map<String, List<String>> finalHeadersForResponse = new HashMap<>();
    // Start with any extra headers that came into this method.
    if (extraResponseHeaders != null) {
        for (Pair<String, List<String>> addMe : extraResponseHeaders) {
            finalHeadersForResponse.put(addMe.getLeft(), addMe.getRight());
        }
    }
    // Then add any from the extraHeadersForResponse() method from this class.
    Map<String, List<String>> evenMoreExtraHeadersForResponse = extraHeadersForResponse(
      frameworkRepresentation, errorContractDTO, highestPriorityStatusCode, filteredClientErrors,
      originalException, request
    );
    if (evenMoreExtraHeadersForResponse != null)
        finalHeadersForResponse.putAll(evenMoreExtraHeadersForResponse);
    // Always add the error_uid header that matches the errorId that was generated.
    finalHeadersForResponse.put("error_uid", Collections.singletonList(errorId));

    // Finally, return the ErrorResponseInfo with the status code, framework response, and headers for the response.
    return new ErrorResponseInfo<>(highestPriorityStatusCode, frameworkRepresentation, finalHeadersForResponse);
}