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

com.palantir.conjure.java.undertow.runtime.ConjureError Maven / Gradle / Ivy

There is a newer version: 8.34.0
Show newest version
/*
 * (c) Copyright 2024 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.undertow.runtime;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.palantir.conjure.java.api.errors.CheckedServiceException;
import com.palantir.conjure.java.api.errors.ErrorType;
import com.palantir.conjure.java.api.errors.RemoteException;
import com.palantir.conjure.java.api.errors.SerializableError;
import com.palantir.conjure.java.api.errors.ServiceException;
import com.palantir.logsafe.Arg;
import com.palantir.logsafe.Preconditions;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;

/**
 * A representation of a Conjure defined error that will be serialized and sent over the wire from a server to a client.
 * 

Previously {@link SerializableError} was used for this purpose. The main difference is that * {@link SerializableError#parameters()} is a {@code Map} while {@link ConjureError#parameters} is a * {@code Map}. When constructing a {@link SerializableError} from a {@link ServiceException}, the error * parameters were converted to strings using {@link Objects#toString} which made it difficult for clients to recover * the structured type. Storing the parameter value as an object allows servers to send Jackson-serialized objects which * the client can convert to their original type. * * @param errorCode A fixed code word identifying the type of error. For errors generated from {@link ServiceException} * and {@link CheckedServiceException}, this corresponds to the {@link ErrorType#code} and is part of * the service's API surface. * @param errorName A fixed name identifying the error. For errors generated from {@link ServiceException} and * {@link CheckedServiceException}, this corresponding to the {@link ErrorType#name} and is part of the * service's API surface. * @param errorInstanceId errorInstanceId A unique identifier for (this instance of) this error. * @param parameters params A list of parameters providing additional context about the error. */ record ConjureError( @JsonProperty("errorCode") String errorCode, @JsonProperty("errorName") String errorName, @JsonProperty("errorInstanceId") String errorInstanceId, @JsonProperty("parameters") Map parameters) { ConjureError { Preconditions.checkNotNull(errorCode, "errorCode cannot be null"); Preconditions.checkNotNull(errorName, "errorName cannot be null"); Preconditions.checkNotNull(errorInstanceId, "errorInstanceId cannot be null"); Preconditions.checkNotNull(parameters, "parameters cannot be null"); } static ConjureError fromCheckedServiceException(CheckedServiceException exception) { Map parameters = new HashMap<>(); for (Arg arg : exception.getArgs()) { if (shouldIncludeArgInParameters(arg)) { parameters.put(arg.getName(), arg.getValue()); } } return new ConjureError( exception.getErrorType().code().name(), exception.getErrorType().name(), exception.getErrorInstanceId(), parameters); } static ConjureError fromServiceException(ServiceException exception) { Map parameters = new HashMap<>(); for (Arg arg : exception.getArgs()) { parameters.put(arg.getName(), Objects.toString(arg.getValue())); } ErrorType errorType = exception.getErrorType(); return new ConjureError(errorType.code().name(), errorType.name(), exception.getErrorInstanceId(), parameters); } /** * {@link RemoteException}s are thrown by clients that send requests to remote services, and indicate an error with * the remote service. When a server forwards a {@link RemoteException}, the forwarded error is considered to be * internal to the server. The parameters from the {@link RemoteException} may not be relevant for the server * forwarding the error, and should not be included. {@link RemoteException}s are logged when received by the server, * so users can retrieve the parameters by finding logs corresponding to the {@code errorInstanceId}. */ static ConjureError fromRemoteException(RemoteException exception) { SerializableError error = exception.getError(); return new ConjureError(error.errorCode(), error.errorName(), error.errorInstanceId(), Collections.emptyMap()); } private static boolean shouldIncludeArgInParameters(Arg arg) { Object obj = arg.getValue(); return obj != null && (!(obj instanceof Optional) || ((Optional) obj).isPresent()) && (!(obj instanceof OptionalInt) || ((OptionalInt) obj).isPresent()) && (!(obj instanceof OptionalLong) || ((OptionalLong) obj).isPresent()) && (!(obj instanceof OptionalDouble) || ((OptionalDouble) obj).isPresent()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy