Search in sources :

Example 51 with DataMap

use of com.linkedin.data.DataMap in project rest.li by linkedin.

the class TestExceptionsResource2 method testGet.

@Test(dataProvider = com.linkedin.restli.internal.common.TestConstants.RESTLI_PROTOCOL_1_2_PREFIX + "exceptionHandlingModesDataProvider")
public void testGet(boolean explicit, ErrorHandlingBehavior errorHandlingBehavior, RootBuilderWrapper<Long, Greeting> builders) throws RemoteInvocationException {
    Response<Greeting> response = null;
    RestLiResponseException exception = null;
    try {
        final Request<Greeting> req = builders.get().id(1L).build();
        ResponseFuture<Greeting> future;
        if (explicit) {
            future = getClient().sendRequest(req, errorHandlingBehavior);
        } else {
            future = getClient().sendRequest(req);
        }
        response = future.getResponse();
        if (!explicit || errorHandlingBehavior == ErrorHandlingBehavior.FAIL_ON_ERROR) {
            Assert.fail("expected exception");
        }
    } catch (RestLiResponseException e) {
        if (!explicit || errorHandlingBehavior == ErrorHandlingBehavior.FAIL_ON_ERROR) {
            exception = e;
        } else {
            Assert.fail("not expected exception");
        }
    }
    if (explicit && errorHandlingBehavior == ErrorHandlingBehavior.TREAT_SERVER_ERROR_AS_SUCCESS) {
        Assert.assertNotNull(response);
        Assert.assertTrue(response.hasError());
        exception = response.getError();
        Assert.assertEquals(response.getStatus(), HttpStatus.S_500_INTERNAL_SERVER_ERROR.getCode());
        Assert.assertNotNull(response.getEntity());
        Assert.assertEquals(response.getEntity(), new Greeting().setMessage("Hello, sorry for the mess"));
    }
    Assert.assertNotNull(exception);
    Assert.assertTrue(exception.hasDecodedResponse());
    Assert.assertEquals(exception.getStatus(), HttpStatus.S_500_INTERNAL_SERVER_ERROR.getCode());
    final DataMap respEntityMap = DataMapUtils.readMap(exception.getResponse());
    Assert.assertEquals(respEntityMap, new Greeting().setMessage("Hello, sorry for the mess").data());
}
Also used : Greeting(com.linkedin.restli.examples.greetings.api.Greeting) RestLiResponseException(com.linkedin.restli.client.RestLiResponseException) DataMap(com.linkedin.data.DataMap) Test(org.testng.annotations.Test)

Example 52 with DataMap

use of com.linkedin.data.DataMap in project rest.li by linkedin.

the class URIDetails method testUriGeneration.

/**
   * Tests the construction and validity of the provided URI. Requires an URIDetails object with the broken down URI.
   *
   * @param createdURIString
   * @param expectedURIDetails
   */
@SuppressWarnings({ "unchecked" })
public static void testUriGeneration(String createdURIString, URIDetails expectedURIDetails) {
    final ProtocolVersion version = expectedURIDetails.getProtocolVersion();
    //Compare the path. Note that in both V1 and V2 all the keys (complex, compound and simple) are serialized recursively
    //in a sorted order. Hence the path will be the same regardless of the underlying Map implementation (order or unordered)
    final String actualPath = createdURIString.split("\\?")[0];
    Assert.assertEquals("The path should be correct", expectedURIDetails._path, actualPath);
    //Move onto the rest of the URI
    final URI createdURI = URI.create(createdURIString);
    //We will parse the created URI into memory and compare it to what's inside the URI details
    final DataMap actualURIDataMap;
    //Note that the actualURIDataMap that is created is composed of query parameters (including ids) and fields
    try {
        if (version.compareTo(AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion()) <= 0) {
            //1.0 - decode and then parse into a data map
            final Map<String, List<String>> queryParameters = UriComponent.decodeQuery(createdURI.getRawQuery(), true);
            actualURIDataMap = QueryParamsDataMap.parseDataMapKeys(queryParameters);
        } else {
            //2.0 - no need to decode as the parsing decodes for us
            final Map<String, List<String>> queryParameters = UriComponent.decodeQuery(createdURI.getRawQuery(), false);
            actualURIDataMap = URIParamUtils.parseUriParams(queryParameters);
        }
        //This will cover everything except fields and ids
        if (expectedURIDetails._queryParams != null) {
            for (final Map.Entry<String, ?> entry : expectedURIDetails._queryParams.entrySet()) {
                Assert.assertNotNull("We should have a valid (non null) key for query param: " + entry.getKey() + " in our created URI", actualURIDataMap.get(entry.getKey()));
                Assert.assertEquals("The value portion of for the query param: " + entry.getKey() + " URI should be correct", actualURIDataMap.get(entry.getKey()), entry.getValue());
            }
        }
        //IDs is to be treated a bit differently since client requests put them in a set
        if (expectedURIDetails._ids != null) {
            final Set<Object> idSet;
            final List<Object> idList;
            if (actualURIDataMap.get("ids") instanceof List) {
                idList = (List<Object>) actualURIDataMap.get("ids");
            } else {
                //Just a single object, (i.e String, DataMap, etc...)
                idList = Arrays.asList(actualURIDataMap.get("ids"));
            }
            idSet = new HashSet<Object>(idList);
            Assert.assertEquals("The set of IDs must match", expectedURIDetails._ids, idSet);
        }
        //Fields is to be treated a bit differently since they could be in any order, hence we compare sets
        if (expectedURIDetails._fields != null) {
            final String[] fieldsArray = ((String) actualURIDataMap.get("fields")).split(",");
            final Set<String> actualFieldSet = new HashSet<String>(Arrays.asList(fieldsArray));
            Assert.assertEquals("The set of projection fields should be correct", expectedURIDetails._fields, actualFieldSet);
        }
        //Now we want to make sure that we have the desired number of keys in the actualURIDataMap
        int desiredKeyCount = 0;
        desiredKeyCount += expectedURIDetails._queryParams == null ? 0 : expectedURIDetails._queryParams.size();
        //values stored in a single key
        desiredKeyCount += expectedURIDetails._fields == null ? 0 : 1;
        //values stored in a single key
        desiredKeyCount += expectedURIDetails._ids == null ? 0 : 1;
        Assert.assertEquals("Incorrect number of keys discovered in URI", desiredKeyCount, actualURIDataMap.size());
    } catch (Exception e) {
        Assert.fail("Unexpected exception when parsing created URI with exception: " + e);
    }
}
Also used : ProtocolVersion(com.linkedin.restli.common.ProtocolVersion) URI(java.net.URI) DataMap(com.linkedin.data.DataMap) QueryParamsDataMap(com.linkedin.restli.internal.common.QueryParamsDataMap) List(java.util.List) DataMap(com.linkedin.data.DataMap) Map(java.util.Map) QueryParamsDataMap(com.linkedin.restli.internal.common.QueryParamsDataMap) HashSet(java.util.HashSet)

Example 53 with DataMap

use of com.linkedin.data.DataMap in project rest.li by linkedin.

the class RestLiAnnotationReader method addActionResourceMethod.

/**
   * Add the given action method to the given resource model,  validating the method is a action before adding.
   * @param model provides the model to add the method to.
   * @param method provides the method to add to the model.
   * @throws ResourceConfigException on validation errors.
   */
private static void addActionResourceMethod(final ResourceModel model, final Method method) {
    Action actionAnno = method.getAnnotation(Action.class);
    if (actionAnno == null) {
        return;
    }
    String actionName = actionAnno.name();
    List<Parameter<?>> parameters = getParameters(model, method, ResourceMethod.ACTION);
    Class<?> returnClass = getActionReturnClass(model, method, actionAnno, actionName);
    TyperefDataSchema returnTyperefSchema = getActionTyperefDataSchema(model, actionAnno, actionName);
    validateActionReturnType(model, method, returnClass, returnTyperefSchema);
    if (!Modifier.isPublic(method.getModifiers())) {
        throw new ResourceConfigException(String.format("Resource '%s' contains non-public action method '%s'.", model.getName(), method.getName()));
    }
    RecordDataSchema recordDataSchema = DynamicRecordMetadata.buildSchema(method.getName(), parameters);
    RecordDataSchema actionReturnRecordDataSchema;
    FieldDef<?> returnFieldDef;
    if (returnClass != Void.TYPE) {
        @SuppressWarnings({ "unchecked", "rawtypes" }) FieldDef<?> nonVoidFieldDef = new FieldDef(ActionResponse.VALUE_NAME, returnClass, getDataSchema(returnClass, returnTyperefSchema));
        returnFieldDef = nonVoidFieldDef;
        actionReturnRecordDataSchema = DynamicRecordMetadata.buildSchema(ActionResponse.class.getName(), Collections.singleton((returnFieldDef)));
    } else {
        returnFieldDef = null;
        actionReturnRecordDataSchema = DynamicRecordMetadata.buildSchema(ActionResponse.class.getName(), Collections.<FieldDef<?>>emptyList());
    }
    if (model.getResourceLevel() == ResourceLevel.ENTITY && actionAnno.resourceLevel() == ResourceLevel.COLLECTION) {
        throw new ResourceConfigException(String.format("Resource '%s' is a simple resource, it cannot contain actions at resource level \"COLLECTION\".", model.getName()));
    }
    DataMap annotationsMap = ResourceModelAnnotation.getAnnotationsMap(method.getAnnotations());
    addDeprecatedAnnotation(annotationsMap, method);
    model.addResourceMethodDescriptor(ResourceMethodDescriptor.createForAction(method, parameters, actionName, getActionResourceLevel(actionAnno, model), returnFieldDef, actionReturnRecordDataSchema, recordDataSchema, getInterfaceType(method), annotationsMap));
}
Also used : FieldDef(com.linkedin.data.template.FieldDef) Action(com.linkedin.restli.server.annotations.Action) TyperefDataSchema(com.linkedin.data.schema.TyperefDataSchema) RecordDataSchema(com.linkedin.data.schema.RecordDataSchema) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) DataMap(com.linkedin.data.DataMap)

Example 54 with DataMap

use of com.linkedin.data.DataMap in project rest.li by linkedin.

the class RestLiAnnotationReader method addTemplateResourceMethod.

/**
   * Handle method that overrides resource template method. Only meaningful for classes
   * that extend a resource template class and only for methods that are NOT annotated
   * with RestMethod. Those are handled in addCrudResourceMethod()
   */
private static void addTemplateResourceMethod(final Class<?> resourceClass, final ResourceModel model, final Method method) {
    // Check if the resource class is derived from one of the resource template classes.
    if (!isResourceTemplateClass(resourceClass)) {
        return;
    }
    // addCrudResourceMethod
    if (isRestMethodAnnotated(method)) {
        return;
    }
    List<Class<?>> parameterTypes = Arrays.asList(method.getParameterTypes());
    boolean partial = parameterTypes.contains(PatchRequest.class) || parameterTypes.contains(BatchPatchRequest.class);
    ResourceMethod resourceMethod = ResourceMethodLookup.fromResourceMethodName(method.getName(), partial);
    if (resourceMethod != null) {
        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 : BatchPatchRequest(com.linkedin.restli.server.BatchPatchRequest) BatchPatchRequest(com.linkedin.restli.server.BatchPatchRequest) PatchRequest(com.linkedin.restli.common.PatchRequest) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) ResourceMethod(com.linkedin.restli.common.ResourceMethod) DataMap(com.linkedin.data.DataMap)

Example 55 with DataMap

use of com.linkedin.data.DataMap in project rest.li by linkedin.

the class RestLiAnnotationReader method processResource.

/**
   * Processes an annotated resource class, producing a ResourceModel.
   *
   * @param resourceClass annotated resource class
   * @return {@link ResourceModel} for the provided resource class
   */
public static ResourceModel processResource(final Class<?> resourceClass, ResourceModel parentResourceModel) {
    final ResourceModel model;
    checkAnnotation(resourceClass);
    if ((resourceClass.isAnnotationPresent(RestLiCollection.class) || resourceClass.isAnnotationPresent(RestLiAssociation.class))) {
        // If any of these annotations, a subclass of KeyValueResource is expected
        if (!KeyValueResource.class.isAssignableFrom(resourceClass)) {
            throw new RestLiInternalException("Resource class '" + resourceClass.getName() + "' declares RestLi annotation but does not implement " + KeyValueResource.class.getName() + " interface.");
        }
        @SuppressWarnings("unchecked") Class<? extends KeyValueResource<?, ?>> clazz = (Class<? extends KeyValueResource<?, ?>>) resourceClass;
        model = processCollection(clazz, parentResourceModel);
    } else if (resourceClass.isAnnotationPresent(RestLiActions.class)) {
        model = processActions(resourceClass, parentResourceModel);
    } else if (resourceClass.isAnnotationPresent(RestLiSimpleResource.class)) {
        @SuppressWarnings("unchecked") Class<? extends SingleObjectResource<?>> clazz = (Class<? extends SingleObjectResource<?>>) resourceClass;
        model = processSingleObjectResource(clazz, parentResourceModel);
    } else {
        throw new ResourceConfigException("Class '" + resourceClass.getName() + "' must be annotated with a valid @RestLi... annotation");
    }
    if (parentResourceModel != null) {
        parentResourceModel.addSubResource(model.getName(), model);
    }
    if (!model.isActions()) {
        checkRestLiDataAnnotations(resourceClass, (RecordDataSchema) getDataSchema(model.getValueClass(), null));
    }
    addAlternativeKeys(model, resourceClass);
    DataMap annotationsMap = ResourceModelAnnotation.getAnnotationsMap(resourceClass.getAnnotations());
    addDeprecatedAnnotation(annotationsMap, resourceClass);
    model.setCustomAnnotation(annotationsMap);
    return model;
}
Also used : KeyValueResource(com.linkedin.restli.server.resources.KeyValueResource) RestLiInternalException(com.linkedin.restli.internal.server.RestLiInternalException) RestLiActions(com.linkedin.restli.server.annotations.RestLiActions) SingleObjectResource(com.linkedin.restli.server.resources.SingleObjectResource) ResourceConfigException(com.linkedin.restli.server.ResourceConfigException) DataMap(com.linkedin.data.DataMap)

Aggregations

DataMap (com.linkedin.data.DataMap)471 Test (org.testng.annotations.Test)238 DataList (com.linkedin.data.DataList)130 ByteString (com.linkedin.data.ByteString)110 HashMap (java.util.HashMap)56 TestUtil.dataMapFromString (com.linkedin.data.TestUtil.dataMapFromString)49 RecordDataSchema (com.linkedin.data.schema.RecordDataSchema)47 TestUtil.dataSchemaFromString (com.linkedin.data.TestUtil.dataSchemaFromString)46 DataSchema (com.linkedin.data.schema.DataSchema)45 Map (java.util.Map)45 ArrayList (java.util.ArrayList)31 MaskTree (com.linkedin.data.transform.filter.request.MaskTree)23 PathSpec (com.linkedin.data.schema.PathSpec)21 RecordTemplate (com.linkedin.data.template.RecordTemplate)21 DataProvider (org.testng.annotations.DataProvider)20 HashSet (java.util.HashSet)19 ArrayDataSchema (com.linkedin.data.schema.ArrayDataSchema)18 PatchTree (com.linkedin.data.transform.patch.request.PatchTree)18 CompoundKey (com.linkedin.restli.common.CompoundKey)18 IOException (java.io.IOException)18