Search in sources :

Example 1 with ParametersServiceError

use of com.linkedin.restli.server.errors.ParametersServiceError in project rest.li by linkedin.

the class RestLiAnnotationReader method buildServiceErrors.

/**
 * Builds a list of {@link ServiceError} objects given a list of codes, a mapping from code to service error, and a
 * mapping from code to parameter names. Also uses the resource class and method to construct an exception message.
 *
 * @param serviceErrorCodes list of service error codes indicating which service errors to build
 * @param serviceErrorCodeMapping mapping from service error code to service error
 * @param paramsMapping mapping from service error codes to array of parameter names
 * @param resourceClass resource class
 * @param method resource method
 * @return list of service errors
 */
private static List<ServiceError> buildServiceErrors(final List<String> serviceErrorCodes, final Map<String, ServiceError> serviceErrorCodeMapping, final Map<String, String[]> paramsMapping, final Class<?> resourceClass, final Method method) {
    final Set<String> existingServiceErrorCodes = new HashSet<>();
    final List<ServiceError> serviceErrors = new ArrayList<>(serviceErrorCodes.size());
    for (String serviceErrorCode : serviceErrorCodes) {
        // Check for duplicate service error codes
        if (existingServiceErrorCodes.contains(serviceErrorCode)) {
            throw new ResourceConfigException(String.format("Duplicate service error code '%s' used in %s", serviceErrorCode, buildExceptionLocationString(resourceClass, method)));
        }
        // Attempt to map this code to its corresponding service error
        if (serviceErrorCodeMapping.containsKey(serviceErrorCode)) {
            final ServiceError serviceError = serviceErrorCodeMapping.get(serviceErrorCode);
            // Validate that this service error doesn't use the ErrorDetails type
            final Class<? extends RecordTemplate> errorDetailType = serviceError.errorDetailType();
            if (errorDetailType != null && errorDetailType.equals(ErrorDetails.class)) {
                throw new ResourceConfigException(String.format("Class '%s' is not meant to be used as an error detail type, please use a more specific " + "model or remove from service error '%s' in %s", errorDetailType.getCanonicalName(), serviceErrorCode, buildExceptionLocationString(resourceClass, method)));
            }
            // Determine if this is a method-level service error with parameters associated with it
            final String[] parameterNames = paramsMapping.get(serviceErrorCode);
            // Depending on if there are service errors, either add it directly or wrap it with the parameter names
            serviceErrors.add(parameterNames == null ? serviceError : new ParametersServiceError(serviceError, parameterNames));
        } else {
            throw new ResourceConfigException(String.format("Unknown service error code '%s' used in %s", serviceErrorCode, buildExceptionLocationString(resourceClass, method)));
        }
        // Mark this code as seen to prevent duplicates
        existingServiceErrorCodes.add(serviceErrorCode);
    }
    return serviceErrors;
}
Also used : ParametersServiceError(com.linkedin.restli.server.errors.ParametersServiceError) ParametersServiceError(com.linkedin.restli.server.errors.ParametersServiceError) ServiceError(com.linkedin.restli.server.errors.ServiceError) ArrayList(java.util.ArrayList) ErrorDetails(com.linkedin.restli.common.ErrorDetails) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) HashSet(java.util.HashSet)

Example 2 with ParametersServiceError

use of com.linkedin.restli.server.errors.ParametersServiceError in project rest.li by linkedin.

the class ResourceModelEncoder method buildServiceErrors.

/**
 * Given a list of service errors, returns a service error schema array record.
 *
 * @param serviceErrors list of service errors to build, assumed to be non-null and non-empty
 * @return service error schema array
 */
private ServiceErrorSchemaArray buildServiceErrors(final List<ServiceError> serviceErrors) {
    final ServiceErrorSchemaArray serviceErrorSchemaArray = new ServiceErrorSchemaArray();
    // For each service error, build a service error schema and append it to the service error schema array
    for (ServiceError serviceError : serviceErrors) {
        ServiceErrorSchema serviceErrorSchema = new ServiceErrorSchema().setStatus(serviceError.httpStatus().getCode()).setCode(serviceError.code());
        final String message = serviceError.message();
        if (message != null) {
            serviceErrorSchema.setMessage(message);
        }
        final Class<?> errorDetailType = serviceError.errorDetailType();
        if (errorDetailType != null) {
            serviceErrorSchema.setErrorDetailType(errorDetailType.getCanonicalName());
        }
        if (serviceError instanceof ParametersServiceError) {
            final String[] parameterNames = ((ParametersServiceError) serviceError).parameterNames();
            if (parameterNames != null && parameterNames.length != 0) {
                serviceErrorSchema.setParameters(new StringArray(Arrays.asList(parameterNames)));
            }
        }
        serviceErrorSchemaArray.add(serviceErrorSchema);
    }
    return serviceErrorSchemaArray;
}
Also used : ParametersServiceError(com.linkedin.restli.server.errors.ParametersServiceError) ServiceError(com.linkedin.restli.server.errors.ServiceError) ParametersServiceError(com.linkedin.restli.server.errors.ParametersServiceError) StringArray(com.linkedin.data.template.StringArray) ServiceErrorSchema(com.linkedin.restli.restspec.ServiceErrorSchema) ServiceErrorSchemaArray(com.linkedin.restli.restspec.ServiceErrorSchemaArray)

Example 3 with ParametersServiceError

use of com.linkedin.restli.server.errors.ParametersServiceError in project rest.li by linkedin.

the class RestLiAnnotationReader method addServiceErrors.

/**
 * Reads annotations on a given method in order to build service errors, which are then added to
 * a given resource method descriptor.
 *
 * @param resourceMethodDescriptor resource method descriptor to add service errors to
 * @param method method annotated with service errors
 */
private static void addServiceErrors(final ResourceMethodDescriptor resourceMethodDescriptor, final Method method) {
    final Class<?> resourceClass = method.getDeclaringClass();
    final ServiceErrorDef serviceErrorDefAnnotation = resourceClass.getAnnotation(ServiceErrorDef.class);
    final ServiceErrors serviceErrorsAnnotation = method.getAnnotation(ServiceErrors.class);
    final ParamError[] paramErrorAnnotations = method.getAnnotationsByType(ParamError.class);
    final List<ServiceError> serviceErrors = buildServiceErrors(serviceErrorDefAnnotation, serviceErrorsAnnotation, paramErrorAnnotations, resourceClass, method);
    if (serviceErrors == null) {
        return;
    }
    // Form a set of parameter names which exist on this method
    final Set<String> acceptableParameterNames = resourceMethodDescriptor.getParameters().stream().map(Parameter::getName).collect(Collectors.toSet());
    // Validate that all parameter names are valid
    for (ServiceError serviceError : serviceErrors) {
        if (serviceError instanceof ParametersServiceError) {
            final String[] parameterNames = ((ParametersServiceError) serviceError).parameterNames();
            if (parameterNames != null) {
                for (String parameterName : parameterNames) {
                    if (!acceptableParameterNames.contains(parameterName)) {
                        throw new ResourceConfigException(String.format("Nonexistent parameter '%s' specified for method-level service error '%s' in %s (valid parameters: %s)", parameterName, serviceError.code(), buildExceptionLocationString(resourceClass, method), acceptableParameterNames.toString()));
                    }
                }
            }
        }
    }
    resourceMethodDescriptor.setServiceErrors(serviceErrors);
}
Also used : ParametersServiceError(com.linkedin.restli.server.errors.ParametersServiceError) ServiceErrorDef(com.linkedin.restli.server.annotations.ServiceErrorDef) ParametersServiceError(com.linkedin.restli.server.errors.ParametersServiceError) ServiceError(com.linkedin.restli.server.errors.ServiceError) ServiceErrors(com.linkedin.restli.server.annotations.ServiceErrors) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) ParamError(com.linkedin.restli.server.annotations.ParamError)

Aggregations

ParametersServiceError (com.linkedin.restli.server.errors.ParametersServiceError)3 ServiceError (com.linkedin.restli.server.errors.ServiceError)3 ResourceConfigException (com.linkedin.restli.server.ResourceConfigException)2 StringArray (com.linkedin.data.template.StringArray)1 ErrorDetails (com.linkedin.restli.common.ErrorDetails)1 ServiceErrorSchema (com.linkedin.restli.restspec.ServiceErrorSchema)1 ServiceErrorSchemaArray (com.linkedin.restli.restspec.ServiceErrorSchemaArray)1 ParamError (com.linkedin.restli.server.annotations.ParamError)1 ServiceErrorDef (com.linkedin.restli.server.annotations.ServiceErrorDef)1 ServiceErrors (com.linkedin.restli.server.annotations.ServiceErrors)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1