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

com.palantir.conjure.java.server.jersey.JsonExceptionMapper Maven / Gradle / Ivy

/*
 * (c) Copyright 2017 Palantir Technologies Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.palantir.conjure.java.server.jersey;

import com.palantir.conjure.java.api.errors.ErrorType;
import com.palantir.conjure.java.api.errors.SerializableError;
import com.palantir.logsafe.SafeArg;
import com.palantir.logsafe.logger.SafeLogger;
import com.palantir.logsafe.logger.SafeLoggerFactory;
import java.util.UUID;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;

/**
 * Writes out generic exceptions as serialized {@link SerializableError}s with {@link MediaType#APPLICATION_JSON JSON
 * media type}. Never forwards the exception message. Subclasses provide an {@link ErrorType} that is used to populate
 * the {@link SerializableError#errorCode} and {@link SerializableError#errorName()} fields as well as the HTTP response
 * status code.
 *
 * 

Consider this call stack, where a caller/browser calls a remote method in a server: * *

caller/browser -> [server] * *

When code in the server throws an {@link Exception} that reaches Jersey, this {@link ExceptionMapper} converts * that exception into an HTTP {@link Response} for return to the caller/browser. */ abstract class JsonExceptionMapper extends ListenableExceptionMapper { private static final SafeLogger log = SafeLoggerFactory.get(JsonExceptionMapper.class); JsonExceptionMapper(ConjureJerseyFeature.ExceptionListener listener) { super(listener); } /** Returns the {@link ErrorType} that this exception corresponds to. */ abstract ErrorType getErrorType(T exception); @Override public final Response toResponseInner(T exception) { String errorInstanceId = UUID.randomUUID().toString(); ErrorType errorType = getErrorType(exception); if (errorType.httpErrorCode() / 100 == 4 /* client error */) { log.info( "Error handling request. {}: {}", SafeArg.of("errorName", errorType.name()), SafeArg.of("errorInstanceId", errorInstanceId), exception); } else { log.error( "Error handling request. {}: {}", SafeArg.of("errorName", errorType.name()), SafeArg.of("errorInstanceId", errorInstanceId), exception); } return createResponse(errorType, errorInstanceId); } static Response createResponse(ErrorType errorType, String errorInstanceId) { return createResponse(errorType.httpErrorCode(), errorType.code().name(), errorType.name(), errorInstanceId); } static Response createResponse(int httpErrorCode, String errorCode, String errorName, String errorInstanceId) { return Response.status(httpErrorCode) .type(MediaType.APPLICATION_JSON) .entity(SerializableError.builder() .errorCode(errorCode) .errorName(errorName) .errorInstanceId(errorInstanceId) .build()) .build(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy