Search in sources :

Example 21 with ResourceConfigException

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

the class RestLiAnnotationReader method buildProjectionParam.

private static Parameter<?> buildProjectionParam(final AnnotationSet annotations, final Class<?> paramType, final Parameter.ParamType projectionType) {
    if (!paramType.equals(MaskTree.class)) {
        throw new ResourceConfigException("Incorrect data type for param: @" + ProjectionParam.class.getSimpleName() + ", @" + Projection.class.getSimpleName() + ", @" + MetadataProjectionParam.class.getSimpleName() + " or @" + PagingProjectionParam.class.getSimpleName() + " parameter annotation must be of type " + MaskTree.class.getName());
    }
    Optional optional = annotations.get(Optional.class);
    @SuppressWarnings({ "unchecked", "rawtypes" }) Parameter<?> param = new Parameter("", paramType, null, optional != null, // default mask is null.
    null, projectionType, false, annotations);
    return param;
}
Also used : Optional(com.linkedin.restli.server.annotations.Optional) MaskTree(com.linkedin.data.transform.filter.request.MaskTree) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException)

Example 22 with ResourceConfigException

use of com.linkedin.restli.server.ResourceConfigException 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)

Example 23 with ResourceConfigException

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

the class RestLiAnnotationReader method buildPathKeysParam.

private static Parameter<?> buildPathKeysParam(final AnnotationSet annotations, final Class<?> paramType, final Class<?> paramAnnotationType) {
    if (!paramType.equals(PathKeys.class)) {
        throw new ResourceConfigException("Incorrect data type for param: @" + PathKeysParam.class.getSimpleName() + " or @" + Keys.class.getSimpleName() + " parameter annotation must be of type " + PathKeys.class.getName());
    }
    Optional optional = annotations.get(Optional.class);
    Parameter.ParamType parameter = null;
    if (paramAnnotationType.equals(Keys.class)) {
        parameter = Parameter.ParamType.PATH_KEYS;
    } else if (paramAnnotationType.equals(PathKeysParam.class)) {
        parameter = Parameter.ParamType.PATH_KEYS_PARAM;
    } else {
        throw new ResourceConfigException("Param Annotation type must be 'PathKeysParam' or the deprecated 'Keys' for PathKeys");
    }
    @SuppressWarnings({ "unchecked", "rawtypes" }) Parameter<?> param = new Parameter("", paramType, null, optional != null, new PathKeysImpl(), parameter, false, annotations);
    return param;
}
Also used : PathKeys(com.linkedin.restli.server.PathKeys) Optional(com.linkedin.restli.server.annotations.Optional) PathKeysParam(com.linkedin.restli.server.annotations.PathKeysParam) PathKeysImpl(com.linkedin.restli.internal.server.PathKeysImpl) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException)

Example 24 with ResourceConfigException

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

the class RestLiAnnotationReader method getResourceType.

private static ResourceType getResourceType(final Class<?> resourceClass) {
    RestLiCollection collAnno = resourceClass.getAnnotation(RestLiCollection.class);
    RestLiAssociation assocAnno = resourceClass.getAnnotation(RestLiAssociation.class);
    RestLiSimpleResource simpleResourceAnno = resourceClass.getAnnotation(RestLiSimpleResource.class);
    if (resourceClass.isAnnotationPresent(RestLiActions.class)) {
        throw new ResourceConfigException("Resource class '" + resourceClass.getName() + "' cannot have both @RestLiCollection and @RestLiActions annotations.");
    }
    int annoCount = 0;
    annoCount += collAnno != null ? 1 : 0;
    annoCount += assocAnno != null ? 1 : 0;
    annoCount += simpleResourceAnno != null ? 1 : 0;
    if (annoCount > 1) {
        throw new ResourceConfigException("Class '" + resourceClass.getName() + "' is annotated " + "with too many RestLi annotations");
    } else if (collAnno != null) {
        return ResourceType.COLLECTION;
    } else if (assocAnno != null) {
        return ResourceType.ASSOCIATION;
    } else if (simpleResourceAnno != null) {
        return ResourceType.SIMPLE;
    } else {
        throw new ResourceConfigException("Class '" + resourceClass.getName() + "' should be annotated " + "with '" + RestLiAssociation.class.getName() + "'" + " or '" + RestLiCollection.class.getName() + "'" + " or '" + RestLiSimpleResource.class.getName() + "'");
    }
}
Also used : RestLiCollection(com.linkedin.restli.server.annotations.RestLiCollection) RestLiSimpleResource(com.linkedin.restli.server.annotations.RestLiSimpleResource) RestLiAssociation(com.linkedin.restli.server.annotations.RestLiAssociation) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException)

Example 25 with ResourceConfigException

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

the class RestLiAnnotationReader method addCrudResourceMethod.

/**
   * Find which rest method annotation is present in the method of the resource, if any,
   * and add MethodDescriptor to ResourceModel.
   *
   * @param resourceClass
   * @param model
   * @param method
   */
private static void addCrudResourceMethod(final Class<?> resourceClass, final ResourceModel model, final Method method) {
    boolean restMethodAnnotationFound = false;
    for (Annotation methodAnnotation : method.getAnnotations()) {
        ResourceMethod resourceMethod = RestMethod.getResourceMethod(methodAnnotation.annotationType());
        if (resourceMethod != null) {
            if (restMethodAnnotationFound) {
                throw new ResourceConfigException("Multiple rest method annotations in method " + method.getName());
            }
            restMethodAnnotationFound = true;
            if (!Modifier.isPublic(method.getModifiers())) {
                throw new ResourceConfigException(String.format("Resource '%s' contains non-public CRUD method '%s'.", model.getName(), method.getName()));
            }
            DataMap annotationsMap = ResourceModelAnnotation.getAnnotationsMap(method.getAnnotations());
            addDeprecatedAnnotation(annotationsMap, method);
            List<Parameter<?>> parameters = getParameters(model, method, resourceMethod);
            model.addResourceMethodDescriptor(ResourceMethodDescriptor.createForRestful(resourceMethod, method, parameters, getInterfaceType(method), annotationsMap));
        }
    }
}
Also used : ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) Annotation(java.lang.annotation.Annotation) ResourceMethod(com.linkedin.restli.common.ResourceMethod) DataMap(com.linkedin.data.DataMap)

Aggregations

ResourceConfigException (com.linkedin.restli.server.ResourceConfigException)27 DataMap (com.linkedin.data.DataMap)7 Optional (com.linkedin.restli.server.annotations.Optional)7 TemplateRuntimeException (com.linkedin.data.template.TemplateRuntimeException)6 RestLiInternalException (com.linkedin.restli.internal.server.RestLiInternalException)6 ParameterizedType (java.lang.reflect.ParameterizedType)4 TyperefDataSchema (com.linkedin.data.schema.TyperefDataSchema)3 RecordTemplate (com.linkedin.data.template.RecordTemplate)3 ResourceMethod (com.linkedin.restli.common.ResourceMethod)3 PagingContext (com.linkedin.restli.server.PagingContext)3 AlternativeKey (com.linkedin.restli.server.annotations.AlternativeKey)3 AssocKey (com.linkedin.restli.server.annotations.AssocKey)3 RecordDataSchema (com.linkedin.data.schema.RecordDataSchema)2 ComplexResourceKey (com.linkedin.restli.common.ComplexResourceKey)2 InterfaceType (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor.InterfaceType)2 CollectionResult (com.linkedin.restli.server.CollectionResult)2 Key (com.linkedin.restli.server.Key)2 PathKeys (com.linkedin.restli.server.PathKeys)2 ResourceContext (com.linkedin.restli.server.ResourceContext)2 ActionParam (com.linkedin.restli.server.annotations.ActionParam)2