Search in sources :

Example 6 with TemplateRuntimeException

use of com.linkedin.data.template.TemplateRuntimeException in project rest.li by linkedin.

the class ArgumentBuilder method buildRegularArgument.

/**
   * Build a method argument from a request parameter that is NOT backed by a schema, i.e.
   * a primitive or an array
   *
   * @param context {@link ResourceContext}
   * @param param {@link Parameter}
   * @return argument value in the correct type
   */
private static Object buildRegularArgument(final ResourceContext context, final Parameter<?> param) {
    String value = ArgumentUtils.argumentAsString(context.getParameter(param.getName()), param.getName());
    final Object convertedValue;
    if (value == null) {
        return null;
    } else {
        if (param.isArray()) {
            convertedValue = buildArrayArgument(context, param);
        } else {
            try {
                convertedValue = ArgumentUtils.convertSimpleValue(value, param.getDataSchema(), param.getType());
            } catch (NumberFormatException e) {
                Class<?> targetClass = DataSchemaUtil.dataSchemaTypeToPrimitiveDataSchemaClass(param.getDataSchema().getDereferencedType());
                // thrown from Integer.valueOf or Long.valueOf
                throw new RoutingException(String.format("Argument parameter '%s' value '%s' must be of type '%s'", param.getName(), value, targetClass.getName()), HttpStatus.S_400_BAD_REQUEST.getCode());
            } catch (IllegalArgumentException e) {
                // thrown from Enum.valueOf
                throw new RoutingException(String.format("Argument parameter '%s' value '%s' is invalid", param.getName(), value), HttpStatus.S_400_BAD_REQUEST.getCode());
            } catch (TemplateRuntimeException e) {
                // thrown from DataTemplateUtil.coerceOutput
                throw new RoutingException(String.format("Argument parameter '%s' value '%s' is invalid. Reason: %s", param.getName(), value, e.getMessage()), HttpStatus.S_400_BAD_REQUEST.getCode());
            }
        }
    }
    return convertedValue;
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException)

Example 7 with TemplateRuntimeException

use of com.linkedin.data.template.TemplateRuntimeException in project rest.li by linkedin.

the class RestLiDataValidator method validateOutputEntity.

private ValidationResult validateOutputEntity(RecordTemplate entity, MaskTree projectionMask) {
    try {
        // Value class from resource model is the only source of truth for record schema.
        // Schema from the record template itself should not be used.
        DataSchema originalSchema = DataTemplateUtil.getSchema(_valueClass);
        // When a projection is defined, we only need to validate the projected fields.
        DataSchema validatingSchema = (projectionMask != null) ? buildSchemaByProjection(originalSchema, projectionMask.getDataMap()) : originalSchema;
        DataSchemaAnnotationValidator validator = new DataSchemaAnnotationValidator(validatingSchema);
        return ValidateDataAgainstSchema.validate(entity.data(), validatingSchema, new ValidationOptions(), validator);
    } catch (TemplateRuntimeException e) {
        return validationResultWithErrorMessage(TEMPLATE_RUNTIME_ERROR);
    }
}
Also used : UnionDataSchema(com.linkedin.data.schema.UnionDataSchema) TyperefDataSchema(com.linkedin.data.schema.TyperefDataSchema) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) ArrayDataSchema(com.linkedin.data.schema.ArrayDataSchema) DataSchema(com.linkedin.data.schema.DataSchema) MapDataSchema(com.linkedin.data.schema.MapDataSchema) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) DataSchemaAnnotationValidator(com.linkedin.data.schema.validator.DataSchemaAnnotationValidator) ValidationOptions(com.linkedin.data.schema.validation.ValidationOptions)

Example 8 with TemplateRuntimeException

use of com.linkedin.data.template.TemplateRuntimeException in project rest.li by linkedin.

the class RestLiAnnotationReader method buildQueryParam.

private static Parameter<?> buildQueryParam(final Method method, final AnnotationSet annotations, final Class<?> paramType) {
    QueryParam queryParam = annotations.get(QueryParam.class);
    Optional optional = annotations.get(Optional.class);
    String paramName = queryParam.value();
    if (INVALID_CHAR_PATTERN.matcher(paramName).find()) {
        throw new ResourceConfigException("Unsupported character in the parameter name :" + paramName);
    }
    Class<? extends TyperefInfo> typerefInfoClass = queryParam.typeref();
    try {
        @SuppressWarnings({ "unchecked", "rawtypes" }) Parameter<?> param = new Parameter(queryParam.value(), paramType, getDataSchema(paramType, getSchemaFromTyperefInfo(typerefInfoClass)), optional != null, getDefaultValueData(optional), Parameter.ParamType.QUERY, true, annotations);
        return param;
    } catch (TemplateRuntimeException e) {
        throw new ResourceConfigException("DataSchema for parameter '" + paramName + "' of type " + paramType.getSimpleName() + " on " + buildMethodMessage(method) + "cannot be found; type is invalid or requires typeref", e);
    } catch (Exception e) {
        throw new ResourceConfigException("Typeref for parameter '" + paramName + "' on " + buildMethodMessage(method) + " cannot be instantiated, " + e.getMessage(), e);
    }
}
Also used : Optional(com.linkedin.restli.server.annotations.Optional) QueryParam(com.linkedin.restli.server.annotations.QueryParam) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) RestLiInternalException(com.linkedin.restli.internal.server.RestLiInternalException)

Example 9 with TemplateRuntimeException

use of com.linkedin.data.template.TemplateRuntimeException in project rest.li by linkedin.

the class RestLiAnnotationReader method buildAlternativeKey.

/**
   * Create an {@link com.linkedin.restli.server.AlternativeKey} object from an {@link com.linkedin.restli.server.annotations.AlternativeKey} annotation.
   *
   * @param resourceName Name of the resource.
   * @param altKeyAnnotation The {@link com.linkedin.restli.server.annotations.AlternativeKey} annotation.
   * @return {@link com.linkedin.restli.server.AlternativeKey} object.
   */
private static com.linkedin.restli.server.AlternativeKey<?, ?> buildAlternativeKey(String resourceName, AlternativeKey altKeyAnnotation) {
    String keyName = altKeyAnnotation.name();
    Class<?> keyType = altKeyAnnotation.keyType();
    Class<? extends TyperefInfo> altKeyTyperef = altKeyAnnotation.keyTyperefClass();
    KeyCoercer<?, ?> keyCoercer;
    try {
        keyCoercer = altKeyAnnotation.keyCoercer().newInstance();
    } catch (InstantiationException e) {
        throw new ResourceConfigException(String.format("KeyCoercer for alternative key '%s' on resource %s cannot be instantiated, %s", keyName, resourceName, e.getMessage()), e);
    } catch (IllegalAccessException e) {
        throw new ResourceConfigException(String.format("KeyCoercer for alternative key '%s' on resource %s cannot be instantiated, %s", keyName, resourceName, e.getMessage()), e);
    }
    try {
        @SuppressWarnings("unchecked") com.linkedin.restli.server.AlternativeKey<?, ?> altKey = new com.linkedin.restli.server.AlternativeKey(keyCoercer, keyType, getDataSchema(keyType, getSchemaFromTyperefInfo(altKeyTyperef)));
        return altKey;
    } catch (TemplateRuntimeException e) {
        throw new ResourceConfigException(String.format("DataSchema for alternative key '%s' of type %s on resource %s cannot be found; type is invalid or requires typeref.", keyName, keyType, resourceName), e);
    } catch (Exception e) {
        throw new ResourceConfigException(String.format("Typeref for alternative key '%s' on resource %s cannot be instantiated, %s", keyName, resourceName, e.getMessage()), e);
    }
}
Also used : TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) RestLiInternalException(com.linkedin.restli.internal.server.RestLiInternalException) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) AlternativeKey(com.linkedin.restli.server.annotations.AlternativeKey)

Example 10 with TemplateRuntimeException

use of com.linkedin.data.template.TemplateRuntimeException in project rest.li by linkedin.

the class ArgumentBuilder method buildArgs.

/**
   * Build arguments for resource method invocation. Combines various types of arguments
   * into a single array.
   *
   * @param positionalArguments pass-through arguments coming from
   *          {@link RestLiArgumentBuilder}
   * @param resourceMethod the resource method
   * @param context {@link ResourceContext}
   * @param template {@link DynamicRecordTemplate}
   * @return array of method argument for method invocation.
   */
@SuppressWarnings("deprecation")
public static Object[] buildArgs(final Object[] positionalArguments, final ResourceMethodDescriptor resourceMethod, final ResourceContext context, final DynamicRecordTemplate template) {
    List<Parameter<?>> parameters = resourceMethod.getParameters();
    Object[] arguments = Arrays.copyOf(positionalArguments, parameters.size());
    fixUpComplexKeySingletonArraysInArguments(arguments);
    boolean attachmentsDesired = false;
    for (int i = positionalArguments.length; i < parameters.size(); ++i) {
        Parameter<?> param = parameters.get(i);
        try {
            if (param.getParamType() == Parameter.ParamType.KEY || param.getParamType() == Parameter.ParamType.ASSOC_KEY_PARAM) {
                Object value = context.getPathKeys().get(param.getName());
                if (value != null) {
                    arguments[i] = value;
                    continue;
                }
            } else if (param.getParamType() == Parameter.ParamType.CALLBACK) {
                continue;
            } else if (param.getParamType() == Parameter.ParamType.PARSEQ_CONTEXT_PARAM || param.getParamType() == Parameter.ParamType.PARSEQ_CONTEXT) {
                // don't know what to fill in yet
                continue;
            } else if (param.getParamType() == Parameter.ParamType.HEADER) {
                HeaderParam headerParam = param.getAnnotations().get(HeaderParam.class);
                String value = context.getRequestHeaders().get(headerParam.value());
                arguments[i] = value;
                continue;
            } else //we must evaluate based on the param type (annotation used)
            if (param.getParamType() == Parameter.ParamType.PROJECTION || param.getParamType() == Parameter.ParamType.PROJECTION_PARAM) {
                arguments[i] = context.getProjectionMask();
                continue;
            } else if (param.getParamType() == Parameter.ParamType.METADATA_PROJECTION_PARAM) {
                arguments[i] = context.getMetadataProjectionMask();
                continue;
            } else if (param.getParamType() == Parameter.ParamType.PAGING_PROJECTION_PARAM) {
                arguments[i] = context.getPagingProjectionMask();
                continue;
            } else if (param.getParamType() == Parameter.ParamType.CONTEXT || param.getParamType() == Parameter.ParamType.PAGING_CONTEXT_PARAM) {
                PagingContext ctx = RestUtils.getPagingContext(context, (PagingContext) param.getDefaultValue());
                arguments[i] = ctx;
                continue;
            } else if (param.getParamType() == Parameter.ParamType.PATH_KEYS || param.getParamType() == Parameter.ParamType.PATH_KEYS_PARAM) {
                arguments[i] = context.getPathKeys();
                continue;
            } else if (param.getParamType() == Parameter.ParamType.PATH_KEY_PARAM) {
                Object value = context.getPathKeys().get(param.getName());
                if (value != null) {
                    arguments[i] = value;
                    continue;
                }
            } else if (param.getParamType() == Parameter.ParamType.RESOURCE_CONTEXT || param.getParamType() == Parameter.ParamType.RESOURCE_CONTEXT_PARAM) {
                arguments[i] = context;
                continue;
            } else if (param.getParamType() == Parameter.ParamType.VALIDATOR_PARAM) {
                RestLiDataValidator validator = new RestLiDataValidator(resourceMethod.getResourceModel().getResourceClass().getAnnotations(), resourceMethod.getResourceModel().getValueClass(), resourceMethod.getMethodType());
                arguments[i] = validator;
                continue;
            } else if (param.getParamType() == Parameter.ParamType.RESTLI_ATTACHMENTS_PARAM) {
                arguments[i] = ((ServerResourceContext) context).getRequestAttachmentReader();
                attachmentsDesired = true;
                continue;
            } else if (param.getParamType() == Parameter.ParamType.POST) {
                // handle action parameters
                if (template != null) {
                    DataMap data = template.data();
                    if (data.containsKey(param.getName())) {
                        arguments[i] = template.getValue(param);
                        continue;
                    }
                }
            } else if (param.getParamType() == Parameter.ParamType.QUERY) {
                Object value;
                if (DataTemplate.class.isAssignableFrom(param.getType())) {
                    value = buildDataTemplateArgument(context, param);
                } else {
                    value = buildRegularArgument(context, param);
                }
                if (value != null) {
                    arguments[i] = value;
                    continue;
                }
            } else if (param.getParamType() == Parameter.ParamType.BATCH || param.getParamType() == Parameter.ParamType.RESOURCE_KEY) {
                // should not come to this routine since it should be handled by passing in positionalArguments
                throw new RoutingException("Parameter '" + param.getName() + "' should be passed in as a positional argument", HttpStatus.S_400_BAD_REQUEST.getCode());
            } else {
                // unknown param type
                throw new RoutingException("Parameter '" + param.getName() + "' has an unknown parameter type '" + param.getParamType().name() + "'", HttpStatus.S_400_BAD_REQUEST.getCode());
            }
        } catch (TemplateRuntimeException e) {
            throw new RoutingException("Parameter '" + param.getName() + "' is invalid", HttpStatus.S_400_BAD_REQUEST.getCode());
        }
        try {
            // check if it is optional parameter
            if (param.isOptional() && param.hasDefaultValue()) {
                arguments[i] = param.getDefaultValue();
            } else if (param.isOptional() && !param.getType().isPrimitive()) {
                // optional primitive parameter must have default value or provided
                arguments[i] = null;
            } else {
                throw new RoutingException("Parameter '" + param.getName() + "' is required", HttpStatus.S_400_BAD_REQUEST.getCode());
            }
        } catch (ResourceConfigException e) {
            // Parameter default value format exception should result in server error code 500.
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Parameter '" + param.getName() + "' default value is invalid", e);
        }
    }
    //that were not needed is safe, but not for request attachments.
    if (!attachmentsDesired && ((ServerResourceContext) context).getRequestAttachmentReader() != null) {
        throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "Resource method endpoint invoked does not accept any request attachments.");
    }
    return arguments;
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) HeaderParam(com.linkedin.restli.server.annotations.HeaderParam) DataMap(com.linkedin.data.DataMap) QueryParamsDataMap(com.linkedin.restli.internal.common.QueryParamsDataMap) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RestLiDataValidator(com.linkedin.restli.common.validation.RestLiDataValidator) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) PagingContext(com.linkedin.restli.server.PagingContext) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) Parameter(com.linkedin.restli.internal.server.model.Parameter) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException)

Aggregations

TemplateRuntimeException (com.linkedin.data.template.TemplateRuntimeException)12 RoutingException (com.linkedin.restli.server.RoutingException)6 ResourceConfigException (com.linkedin.restli.server.ResourceConfigException)5 RestLiInternalException (com.linkedin.restli.internal.server.RestLiInternalException)4 ArrayDataSchema (com.linkedin.data.schema.ArrayDataSchema)3 Optional (com.linkedin.restli.server.annotations.Optional)3 DataList (com.linkedin.data.DataList)2 DataMap (com.linkedin.data.DataMap)2 DataSchema (com.linkedin.data.schema.DataSchema)2 RecordDataSchema (com.linkedin.data.schema.RecordDataSchema)2 TyperefDataSchema (com.linkedin.data.schema.TyperefDataSchema)2 ValidationOptions (com.linkedin.data.schema.validation.ValidationOptions)2 CompoundKey (com.linkedin.restli.common.CompoundKey)2 PathSegmentSyntaxException (com.linkedin.restli.internal.common.PathSegment.PathSegmentSyntaxException)2 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)2 MapDataSchema (com.linkedin.data.schema.MapDataSchema)1 UnionDataSchema (com.linkedin.data.schema.UnionDataSchema)1 DataSchemaAnnotationValidator (com.linkedin.data.schema.validator.DataSchemaAnnotationValidator)1 DataTemplate (com.linkedin.data.template.DataTemplate)1 ComplexResourceKey (com.linkedin.restli.common.ComplexResourceKey)1