Search in sources :

Example 6 with RoutingException

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

the class RestLiRouter method parseCompoundKey.

private static CompoundKey parseCompoundKey(final ResourceModel resource, final ServerResourceContext context, final String pathSegment) {
    CompoundKey compoundKey;
    try {
        compoundKey = ArgumentUtils.parseCompoundKey(pathSegment, resource.getKeys(), context.getRestliProtocolVersion());
    } catch (PathSegmentSyntaxException e) {
        throw new RoutingException(String.format("input %s is not a Compound key", pathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
    } catch (IllegalArgumentException e) {
        throw new RoutingException(String.format("input %s is not a Compound key", pathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
    } catch (TemplateRuntimeException e) {
        // thrown from DateTemplateUtil.coerceOutput
        throw new RoutingException(String.format("Compound key parameter value %s is invalid", pathSegment), HttpStatus.S_400_BAD_REQUEST.getCode(), e);
    }
    for (String simpleKeyName : compoundKey.getPartKeys()) {
        context.getPathKeys().append(simpleKeyName, compoundKey.getPart(simpleKeyName));
    }
    context.getPathKeys().append(resource.getKeyName(), compoundKey);
    return compoundKey;
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) PathSegmentSyntaxException(com.linkedin.restli.internal.common.PathSegment.PathSegmentSyntaxException) CompoundKey(com.linkedin.restli.common.CompoundKey) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException)

Example 7 with RoutingException

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

the class RestLiRouter method parseBatchKeysParameter.

private void parseBatchKeysParameter(final ResourceModel resource, final ServerResourceContext context) {
    Class<?> keyClass = resource.getKeyClass();
    ProtocolVersion version = context.getRestliProtocolVersion();
    final Set<Object> batchKeys;
    try {
        if (context.getParameters().containsKey(RestConstants.ALT_KEY_PARAM)) {
            batchKeys = parseAlternativeBatchKeys(resource, context);
        } else if (ComplexResourceKey.class.equals(keyClass)) {
            // Parse all query parameters into a data map.
            DataMap allParametersDataMap = context.getParameters();
            // Get the batch request keys from the IDS list at the root of the map.
            DataList batchIds = allParametersDataMap.getDataList(RestConstants.QUERY_BATCH_IDS_PARAM);
            if (batchIds == null) {
                batchKeys = null;
            } else if (batchIds.isEmpty()) {
                batchKeys = Collections.emptySet();
            } else {
                batchKeys = new HashSet<Object>();
                // Validate the complex keys and put them into the context batch keys
                for (Object complexKey : batchIds) {
                    if (!(complexKey instanceof DataMap)) {
                        log.warn("Invalid structure of key '" + complexKey.toString() + "', skipping key.");
                        context.getBatchKeyErrors().put(complexKey, new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST));
                        continue;
                    }
                    batchKeys.add(ComplexResourceKey.buildFromDataMap((DataMap) complexKey, ComplexKeySpec.forClassesMaybeNull(resource.getKeyKeyClass(), resource.getKeyParamsClass())));
                }
            }
        } else if (CompoundKey.class.equals(keyClass) && version.compareTo(AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion()) >= 0) {
            DataMap allParametersDataMap = context.getParameters();
            // Get the batch request keys from the IDS list at the root of the map.
            DataList batchIds = allParametersDataMap.getDataList(RestConstants.QUERY_BATCH_IDS_PARAM);
            if (batchIds == null) {
                batchKeys = null;
            } else if (batchIds.isEmpty()) {
                batchKeys = Collections.emptySet();
            } else {
                batchKeys = new HashSet<Object>();
                // Validate the compound keys and put them into the contex batch keys
                for (Object compoundKey : batchIds) {
                    if (!(compoundKey instanceof DataMap)) {
                        log.warn("Invalid structure of key '" + compoundKey.toString() + "', skipping key.");
                        context.getBatchKeyErrors().put(compoundKey.toString(), new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST));
                        continue;
                    }
                    CompoundKey finalKey;
                    try {
                        finalKey = ArgumentUtils.dataMapToCompoundKey((DataMap) compoundKey, resource.getKeys());
                    } catch (IllegalArgumentException e) {
                        log.warn("Invalid structure of key '" + compoundKey.toString() + "', skipping key.");
                        context.getBatchKeyErrors().put(compoundKey.toString(), new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST));
                        continue;
                    }
                    batchKeys.add(finalKey);
                }
            }
        } else // collection batch get in v2, collection or association batch get in v1
        if (context.hasParameter(RestConstants.QUERY_BATCH_IDS_PARAM)) {
            batchKeys = new HashSet<Object>();
            List<String> ids = context.getParameterValues(RestConstants.QUERY_BATCH_IDS_PARAM);
            if (version.compareTo(AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion()) >= 0) {
                for (String id : ids) {
                    Key key = resource.getPrimaryKey();
                    Object value;
                    try {
                        // in v2, compound keys have already been converted and dealt with, so all we need to do here is convert simple values.
                        value = ArgumentUtils.convertSimpleValue(id, key.getDataSchema(), key.getType());
                        batchKeys.add(value);
                    } catch (NumberFormatException e) {
                        throw new RoutingException("NumberFormatException parsing batch key '" + id + "'", HttpStatus.S_400_BAD_REQUEST.getCode(), e);
                    } catch (IllegalArgumentException e) {
                        throw new RoutingException("IllegalArgumentException parsing batch key '" + id + "'", HttpStatus.S_400_BAD_REQUEST.getCode(), e);
                    }
                }
            } else {
                for (String id : ids) {
                    try {
                        // in v1, compound keys have not been fully parsed or dealt with yet, so we need to take them into account.
                        Object value = parseKeyFromBatchV1(id, resource);
                        batchKeys.add(value);
                    } catch (NumberFormatException e) {
                        log.warn("Caught NumberFormatException parsing batch key '" + id + "', skipping key.");
                        context.getBatchKeyErrors().put(id, new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, null, e));
                    } catch (IllegalArgumentException e) {
                        log.warn("Caught IllegalArgumentException parsing batch key '" + id + "', skipping key.");
                        context.getBatchKeyErrors().put(id, new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, null, e));
                    } catch (PathSegmentSyntaxException e) {
                        log.warn("Caught IllegalArgumentException parsing batch key '" + id + "', skipping key.");
                        context.getBatchKeyErrors().put(id, new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, null, e));
                    }
                }
            }
        } else {
            batchKeys = null;
        }
    } catch (TemplateRuntimeException e) {
        // thrown from DateTemplateUtil.coerceOutput
        throw new RoutingException("Batch key parameter value is invalid", HttpStatus.S_400_BAD_REQUEST.getCode(), e);
    }
    context.getPathKeys().setBatchKeys(batchKeys);
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) CompoundKey(com.linkedin.restli.common.CompoundKey) ProtocolVersion(com.linkedin.restli.common.ProtocolVersion) DataMap(com.linkedin.data.DataMap) DataList(com.linkedin.data.DataList) PathSegmentSyntaxException(com.linkedin.restli.internal.common.PathSegment.PathSegmentSyntaxException) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) LinkedList(java.util.LinkedList) DataList(com.linkedin.data.DataList) List(java.util.List) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) Key(com.linkedin.restli.server.Key) CompoundKey(com.linkedin.restli.common.CompoundKey) HashSet(java.util.HashSet)

Example 8 with RoutingException

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

the class RestLiRouter method parseAlternativeBatchKeys.

private static Set<Object> parseAlternativeBatchKeys(final ResourceModel resource, final ServerResourceContext context) {
    String altKeyName = context.getParameter(RestConstants.ALT_KEY_PARAM);
    List<String> ids = context.getParameterValues(RestConstants.QUERY_BATCH_IDS_PARAM);
    Set<Object> batchKeys = new HashSet<Object>();
    if (ids == null) {
        batchKeys = null;
    } else if (ids.isEmpty()) {
        batchKeys = Collections.emptySet();
    } else {
        if (!resource.getAlternativeKeys().containsKey(altKeyName)) {
            throw new RoutingException(String.format("Resource '%s' does not have an alternative key named '%s'", resource.getName(), altKeyName), HttpStatus.S_400_BAD_REQUEST.getCode());
        }
        for (String id : ids) {
            try {
                batchKeys.add(ArgumentUtils.translateFromAlternativeKey(ArgumentUtils.parseAlternativeKey(id, altKeyName, resource, context.getRestliProtocolVersion()), altKeyName, resource));
            } catch (InvalidAlternativeKeyException e) {
                log.warn(String.format("Invalid alternative key '%s', skipping key.", id));
                context.getBatchKeyErrors().put(id, new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, e));
            } catch (AlternativeKeyCoercerException e) {
                throw new RoutingException(String.format("Unexpected error when coercing alternative key '%s': %s", id, e.getMessage()), HttpStatus.S_500_INTERNAL_SERVER_ERROR.getCode());
            }
        }
    }
    return batchKeys;
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) InvalidAlternativeKeyException(com.linkedin.data.template.InvalidAlternativeKeyException) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) AlternativeKeyCoercerException(com.linkedin.restli.internal.server.util.AlternativeKeyCoercerException) HashSet(java.util.HashSet)

Example 9 with RoutingException

use of com.linkedin.restli.server.RoutingException 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 10 with RoutingException

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

the class RestLiRouter method parseAlternativeKey.

/**
   * Coercers the alternative key into a primary key and puts it into path keys.
   *
   * @param resource the {@link com.linkedin.restli.internal.server.model.ResourceModel} of the resource.
   * @param context the {@link com.linkedin.restli.internal.server.ServerResourceContext} of the request.
   * @param currentPathSegment the serialized alternative key.
   */
private static <K> void parseAlternativeKey(final ResourceModel resource, final ServerResourceContext context, final String currentPathSegment) {
    String altKeyName = context.getParameter(RestConstants.ALT_KEY_PARAM);
    Object alternativeKey;
    try {
        alternativeKey = ArgumentUtils.parseAlternativeKey(currentPathSegment, context.getParameter(RestConstants.ALT_KEY_PARAM), resource, context.getRestliProtocolVersion());
    } catch (IllegalArgumentException e) {
        throw new RoutingException(e.getMessage(), HttpStatus.S_400_BAD_REQUEST.getCode());
    }
    try {
        K canonicalKey = ArgumentUtils.translateFromAlternativeKey(alternativeKey, altKeyName, resource);
        context.getPathKeys().append(resource.getKeyName(), canonicalKey);
    } catch (InvalidAlternativeKeyException e) {
        throw new RoutingException(e.getMessage(), HttpStatus.S_400_BAD_REQUEST.getCode());
    } catch (AlternativeKeyCoercerException e) {
        throw new RoutingException("KeyCoercer threw an unexpected exception", HttpStatus.S_500_INTERNAL_SERVER_ERROR.getCode(), e);
    }
}
Also used : RoutingException(com.linkedin.restli.server.RoutingException) InvalidAlternativeKeyException(com.linkedin.data.template.InvalidAlternativeKeyException) AlternativeKeyCoercerException(com.linkedin.restli.internal.server.util.AlternativeKeyCoercerException)

Aggregations

RoutingException (com.linkedin.restli.server.RoutingException)41 RestRequest (com.linkedin.r2.message.rest.RestRequest)15 RoutingResult (com.linkedin.restli.internal.server.RoutingResult)15 ResourceMethodDescriptor (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor)15 Test (org.testng.annotations.Test)15 ResourceModel (com.linkedin.restli.internal.server.model.ResourceModel)12 DataMap (com.linkedin.data.DataMap)7 ServerResourceContext (com.linkedin.restli.internal.server.ServerResourceContext)7 TemplateRuntimeException (com.linkedin.data.template.TemplateRuntimeException)6 ResourceContext (com.linkedin.restli.server.ResourceContext)6 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)6 RequestContext (com.linkedin.r2.message.RequestContext)5 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)5 CompoundKey (com.linkedin.restli.common.CompoundKey)5 RestLiRequestData (com.linkedin.restli.server.RestLiRequestData)5 ByteString (com.linkedin.data.ByteString)4 ResourceContextImpl (com.linkedin.restli.internal.server.ResourceContextImpl)4 RestLiInternalException (com.linkedin.restli.internal.server.RestLiInternalException)4 CustomString (com.linkedin.restli.server.custom.types.CustomString)4 RestLiTestHelper.buildResourceModel (com.linkedin.restli.server.test.RestLiTestHelper.buildResourceModel)4