Search in sources :

Example 11 with PatchRequest

use of com.linkedin.restli.common.PatchRequest in project rest.li by linkedin.

the class RestLiValidationFilter method onRequest.

@Override
public CompletableFuture<Void> onRequest(final FilterRequestContext requestContext) {
    // are spotted early
    if (shouldValidateOnResponse(requestContext)) {
        MaskTree projectionMask = requestContext.getProjectionMask();
        if (projectionMask != null) {
            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(requestContext.getFilterResourceModel().getValueClass());
                DataSchema validatingSchema = constructValidatingSchema(requestContext, originalSchema, projectionMask.getDataMap(), _nonSchemaFieldsToAllowInProjectionMask);
                // Put validating schema in scratchpad for use in onResponse
                requestContext.getFilterScratchpad().put(VALIDATING_SCHEMA_KEY, validatingSchema);
            } catch (InvalidProjectionException e) {
                throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, e.getMessage());
            } catch (TemplateRuntimeException e) {
                throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, TEMPLATE_RUNTIME_EXCEPTION_MESSAGE);
            }
        }
    }
    if (!shouldValidateOnRequest(requestContext)) {
        return CompletableFuture.completedFuture(null);
    }
    Class<?> resourceClass = requestContext.getFilterResourceModel().getResourceClass();
    if (UnstructuredDataUtil.isUnstructuredDataClass(resourceClass)) {
        return CompletableFuture.completedFuture(null);
    }
    ResourceMethod method = requestContext.getMethodType();
    RestLiDataValidator validator = createRequestRestLiDataValidator(requestContext);
    RestLiRequestData requestData = requestContext.getRequestData();
    ValidationResult result;
    switch(method) {
        case CREATE:
        case UPDATE:
            result = validator.validateInput(requestData.getEntity());
            if (!result.isValid()) {
                throw constructRestLiServiceException(result.getMessages(), result.getMessages().toString());
            }
            break;
        case PARTIAL_UPDATE:
            result = validator.validateInput((PatchRequest<?>) requestData.getEntity());
            if (!result.isValid()) {
                throw constructRestLiServiceException(result.getMessages(), result.getMessages().toString());
            }
            break;
        case BATCH_CREATE:
            StringBuilder errorMessage = new StringBuilder();
            Map<String, Collection<Message>> messages = new HashMap<>();
            int index = 0;
            for (RecordTemplate entity : requestData.getBatchEntities()) {
                result = validator.validateInput(entity);
                if (!result.isValid()) {
                    errorMessage.append("Index: ").append(index).append(", ").append(result.getMessages().toString());
                    messages.put(String.valueOf(index), result.getMessages());
                }
                ++index;
            }
            if (errorMessage.length() > 0) {
                throw constructRestLiServiceException(messages, errorMessage.toString());
            }
            break;
        case BATCH_UPDATE:
        case BATCH_PARTIAL_UPDATE:
            ProtocolVersion protocolVersion = requestContext.getRestliProtocolVersion();
            StringBuilder stringBuilder = new StringBuilder();
            Map<String, Collection<Message>> errorMessages = new HashMap<>();
            for (Map.Entry<?, ? extends RecordTemplate> entry : requestData.getBatchKeyEntityMap().entrySet()) {
                if (method == ResourceMethod.BATCH_UPDATE) {
                    result = validator.validateInput(entry.getValue());
                } else {
                    result = validator.validateInput((PatchRequest<?>) entry.getValue());
                }
                if (!result.isValid()) {
                    stringBuilder.append("Key: ").append(entry.getKey()).append(", ").append(result.getMessages().toString());
                    errorMessages.put(URIParamUtils.encodeKeyForBody(entry.getKey(), false, protocolVersion), result.getMessages());
                }
            }
            if (stringBuilder.length() > 0) {
                throw constructRestLiServiceException(errorMessages, stringBuilder.toString());
            }
            break;
        default:
            break;
    }
    return CompletableFuture.completedFuture(null);
}
Also used : InvalidProjectionException(com.linkedin.restli.common.util.ProjectionMaskApplier.InvalidProjectionException) HashMap(java.util.HashMap) ValidationResult(com.linkedin.data.schema.validation.ValidationResult) PatchRequest(com.linkedin.restli.common.PatchRequest) ProtocolVersion(com.linkedin.restli.common.ProtocolVersion) DataSchema(com.linkedin.data.schema.DataSchema) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) MaskTree(com.linkedin.data.transform.filter.request.MaskTree) RestLiDataValidator(com.linkedin.restli.common.validation.RestLiDataValidator) RecordTemplate(com.linkedin.data.template.RecordTemplate) TemplateRuntimeException(com.linkedin.data.template.TemplateRuntimeException) Collection(java.util.Collection) HashMap(java.util.HashMap) DataMap(com.linkedin.data.DataMap) Map(java.util.Map) ResourceMethod(com.linkedin.restli.common.ResourceMethod) RestLiRequestData(com.linkedin.restli.server.RestLiRequestData)

Example 12 with PatchRequest

use of com.linkedin.restli.common.PatchRequest in project rest.li by linkedin.

the class TestBatchPatchArgumentBuilder method argumentData.

@DataProvider(name = "argumentData")
private Object[][] argumentData() {
    Map<String, Object> aMap1 = new HashMap<>();
    aMap1.put("a", "someString");
    Map<String, Object> setMap1 = new HashMap<>();
    setMap1.put("$set", new DataMap(aMap1));
    Map<String, Object> patchMap1 = new HashMap<>();
    patchMap1.put("patch", new DataMap(setMap1));
    PatchRequest<MyComplexKey> patch1 = new PatchRequest<>(new DataMap(patchMap1));
    Map<String, Object> aMap2 = new HashMap<>();
    aMap2.put("a", "someOtherString");
    Map<String, Object> setMap2 = new HashMap<>();
    setMap2.put("$set", new DataMap(aMap2));
    Map<String, Object> data2 = new HashMap<>();
    data2.put("patch", new DataMap(setMap2));
    PatchRequest<MyComplexKey> patch2 = new PatchRequest<>(new DataMap(data2));
    @SuppressWarnings("rawtypes") PatchRequest[] patches = new PatchRequest[] { patch1, patch2 };
    Object[] simpleKeys = new Object[] { "simple", "(s:pe%cial)" };
    Object[] compoundKeys = new Object[] { new CompoundKey().append("string1", "apples").append("string2", "oranges"), new CompoundKey().append("string1", "simple").append("string2", "(s:pe%cial)") };
    Object[] complexResourceKeys = new Object[] { new ComplexResourceKey<>(new MyComplexKey().setA("simple").setB(111L), new EmptyRecord()), new ComplexResourceKey<>(new MyComplexKey().setA("(s:pe%cial)").setB(222L), new EmptyRecord()) };
    return new Object[][] { { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("stringKey", String.class, new StringDataSchema()), null, "{\"entities\":{\"simple\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"(s:pe%cial)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", simpleKeys, patches }, { AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), new Key("stringKey", String.class, new StringDataSchema()), null, "{\"entities\":{\"simple\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"(s:pe%cial)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", simpleKeys, patches }, { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("compoundKey", CompoundKey.class, null), new Key[] { new Key("string1", String.class), new Key("string2", String.class) }, "{\"entities\":{\"string1=apples&string2=oranges\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"string1=simple&string2=(s:pe%25cial)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", compoundKeys, patches }, { AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), new Key("compoundKey", CompoundKey.class, null), new Key[] { new Key("string1", String.class), new Key("string2", String.class) }, "{\"entities\":{\"(string1:apples,string2:oranges)\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"(string1:simple,string2:%28s%3Ape%25cial%29)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", compoundKeys, patches }, { AllProtocolVersions.RESTLI_PROTOCOL_1_0_0.getProtocolVersion(), new Key("complexKey", ComplexResourceKey.class, null), null, "{\"entities\":{\"a=simple&b=111\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}," + "\"a=(s:pe%25cial)&b=222\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}}}", complexResourceKeys, patches }, { AllProtocolVersions.RESTLI_PROTOCOL_2_0_0.getProtocolVersion(), new Key("complexKey", ComplexResourceKey.class, null), null, "{\"entities\":{\"($params:(),a:%28s%3Ape%25cial%29,b:222)\":{\"patch\":{\"$set\":{\"a\":\"someOtherString\"}}}," + "\"($params:(),a:simple,b:111)\":{\"patch\":{\"$set\":{\"a\":\"someString\"}}}}}", complexResourceKeys, patches } };
}
Also used : EmptyRecord(com.linkedin.restli.common.EmptyRecord) MyComplexKey(com.linkedin.restli.common.test.MyComplexKey) HashMap(java.util.HashMap) CompoundKey(com.linkedin.restli.common.CompoundKey) PatchRequest(com.linkedin.restli.common.PatchRequest) BatchPatchRequest(com.linkedin.restli.server.BatchPatchRequest) DataMap(com.linkedin.data.DataMap) StringDataSchema(com.linkedin.data.schema.StringDataSchema) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) MyComplexKey(com.linkedin.restli.common.test.MyComplexKey) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) Key(com.linkedin.restli.server.Key) CompoundKey(com.linkedin.restli.common.CompoundKey) DataProvider(org.testng.annotations.DataProvider)

Example 13 with PatchRequest

use of com.linkedin.restli.common.PatchRequest in project rest.li by linkedin.

the class TestClientBuilders method testBatchPartialUpdateRequestBuilder.

// need suppress on the method because the more specific suppress isn't being obeyed.
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test(dataProvider = TestConstants.RESTLI_PROTOCOL_1_2_PREFIX + "batch")
public void testBatchPartialUpdateRequestBuilder(URIDetails expectedURIDetails) {
    BatchPartialUpdateRequestBuilder<Long, TestRecord> builder = new BatchPartialUpdateRequestBuilder<>(TEST_URI, TestRecord.class, _COLL_SPEC, RestliRequestOptions.DEFAULT_OPTIONS);
    builder.input(1L, new PatchRequest<>());
    builder.input(2L, new PatchRequest<>());
    builder.input(3L, new PatchRequest<>());
    BatchPartialUpdateRequest<Long, TestRecord> request = builder.appendSingleAttachment(_dataSourceWriterA).appendMultipleAttachments(_dataSourceIterator).appendSingleAttachment(_dataSourceWriterB).build();
    testBaseUriGeneration(request, expectedURIDetails.getProtocolVersion());
    Assert.assertEquals(request.getObjectIds(), new HashSet<>(Arrays.asList(1L, 2L, 3L)));
    Assert.assertEquals(request.isSafe(), false);
    Assert.assertEquals(request.isIdempotent(), false);
    // verify partialUpdateInputMap
    Map<Long, PatchRequest<TestRecord>> expectedPartialUpdateMap = new HashMap<>();
    expectedPartialUpdateMap.put(1L, new PatchRequest<>());
    expectedPartialUpdateMap.put(2L, new PatchRequest<>());
    expectedPartialUpdateMap.put(3L, new PatchRequest<>());
    Assert.assertNotNull(request.getPartialUpdateInputMap());
    Assert.assertEquals(request.getPartialUpdateInputMap(), expectedPartialUpdateMap);
    @SuppressWarnings({ "unchecked", "rawtypes" }) BatchRequest<PatchRequest<TestRecord>> expectedRequest = new BatchRequest(new DataMap(), PatchRequest.class);
    expectedRequest.getEntities().put("1", new PatchRequest<>());
    expectedRequest.getEntities().put("2", new PatchRequest<>());
    expectedRequest.getEntities().put("3", new PatchRequest<>());
    KeyValueRecordFactory<Long, PatchRequest> factory = new KeyValueRecordFactory<>(Long.class, null, null, null, PatchRequest.class);
    CollectionRequest<KeyValueRecord> collectionRequest = buildCollectionRequest(factory, new Long[] { 1L, 2L, 3L }, new PatchRequest[] { new PatchRequest(), new PatchRequest(), new PatchRequest() });
    checkBasicRequest(request, expectedURIDetails, ResourceMethod.BATCH_PARTIAL_UPDATE, collectionRequest, expectedRequest, Collections.<String, String>emptyMap(), _streamingDataSources);
}
Also used : BatchRequest(com.linkedin.restli.common.BatchRequest) HashMap(java.util.HashMap) KeyValueRecordFactory(com.linkedin.restli.common.KeyValueRecordFactory) PatchRequest(com.linkedin.restli.common.PatchRequest) DataMap(com.linkedin.data.DataMap) KeyValueRecord(com.linkedin.restli.common.KeyValueRecord) TestRecord(com.linkedin.restli.client.test.TestRecord) Test(org.testng.annotations.Test)

Example 14 with PatchRequest

use of com.linkedin.restli.common.PatchRequest in project rest.li by linkedin.

the class TestComplexKeysResource method testBatchPartialUpdateMain.

private void testBatchPartialUpdateMain(RootBuilderWrapper.MethodBuilderWrapper<ComplexResourceKey<TwoPartKey, TwoPartKey>, Message, BatchKVResponse<ComplexResourceKey<TwoPartKey, TwoPartKey>, UpdateStatus>> requestBuilder, BatchGetEntityRequestBuilder<ComplexResourceKey<TwoPartKey, TwoPartKey>, Message> batchGetRequestBuilder) throws RemoteInvocationException {
    Message message = new Message();
    message.setTone(Tone.FRIENDLY);
    PatchRequest<Message> patch = PatchGenerator.diffEmpty(message);
    final Map<ComplexResourceKey<TwoPartKey, TwoPartKey>, PatchRequest<Message>> inputs = new HashMap<>();
    ComplexResourceKey<TwoPartKey, TwoPartKey> key1 = getComplexKey(StringTestKeys.SIMPLEKEY, StringTestKeys.SIMPLEKEY2);
    ComplexResourceKey<TwoPartKey, TwoPartKey> key2 = getComplexKey(StringTestKeys.URL, StringTestKeys.URL2);
    inputs.put(key1, patch);
    inputs.put(key2, patch);
    final Request<BatchKVResponse<ComplexResourceKey<TwoPartKey, TwoPartKey>, UpdateStatus>> request = requestBuilder.patchInputs(inputs).build();
    final ResponseFuture<BatchKVResponse<ComplexResourceKey<TwoPartKey, TwoPartKey>, UpdateStatus>> future = getClient().sendRequest(request);
    final BatchKVResponse<ComplexResourceKey<TwoPartKey, TwoPartKey>, UpdateStatus> response = future.getResponse().getEntity();
    for (Map.Entry<ComplexResourceKey<TwoPartKey, TwoPartKey>, UpdateStatus> resp : response.getResults().entrySet()) {
        Assert.assertTrue(inputs.containsKey(resp.getKey()));
        Assert.assertEquals(resp.getValue().getStatus().intValue(), 204);
    }
    Assert.assertNotNull(response.getResults().get(key1));
    Assert.assertNotNull(response.getResults().get(key2));
    Assert.assertTrue(response.getErrors().isEmpty());
    ArrayList<ComplexResourceKey<TwoPartKey, TwoPartKey>> ids = new ArrayList<>();
    ids.add(key1);
    ids.add(key2);
    Request<BatchKVResponse<ComplexResourceKey<TwoPartKey, TwoPartKey>, EntityResponse<Message>>> batchGetRequest = batchGetRequestBuilder.ids(ids).build();
    ResponseFuture<BatchKVResponse<ComplexResourceKey<TwoPartKey, TwoPartKey>, EntityResponse<Message>>> batchGetFuture = getClient().sendRequest(batchGetRequest);
    BatchKVResponse<ComplexResourceKey<TwoPartKey, TwoPartKey>, EntityResponse<Message>> batchGetResponse = batchGetFuture.getResponse().getEntity();
    Assert.assertEquals(batchGetResponse.getResults().get(key1).getEntity().getTone(), Tone.FRIENDLY);
    Assert.assertEquals(batchGetResponse.getResults().get(key2).getEntity().getTone(), Tone.FRIENDLY);
}
Also used : TwoPartKey(com.linkedin.restli.examples.greetings.api.TwoPartKey) UpdateStatus(com.linkedin.restli.common.UpdateStatus) Message(com.linkedin.restli.examples.greetings.api.Message) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) PatchRequest(com.linkedin.restli.common.PatchRequest) BatchKVResponse(com.linkedin.restli.client.response.BatchKVResponse) EntityResponse(com.linkedin.restli.common.EntityResponse) ComplexResourceKey(com.linkedin.restli.common.ComplexResourceKey) Map(java.util.Map) HashMap(java.util.HashMap) DataMap(com.linkedin.data.DataMap)

Example 15 with PatchRequest

use of com.linkedin.restli.common.PatchRequest in project rest.li by linkedin.

the class TestGreetingsClient method testBatchPartialUpdate.

@Test(dataProvider = com.linkedin.restli.internal.common.TestConstants.RESTLI_PROTOCOL_1_2_PREFIX + "requestBuilderDataProvider")
public void testBatchPartialUpdate(RootBuilderWrapper<Long, Greeting> builders) throws RemoteInvocationException, CloneNotSupportedException {
    List<Greeting> greetings = generateBatchTestData(3, "BatchPatch", Tone.FRIENDLY);
    @SuppressWarnings("unchecked") List<Long> createdIds = createBatchTestDataSerially(builders, greetings);
    addIdsToGeneratedGreetings(createdIds, greetings);
    // Patch the created Greetings
    Map<Long, PatchRequest<Greeting>> patchedGreetingsDiffs = new HashMap<>();
    List<Greeting> patchedGreetings = new ArrayList<>();
    for (Greeting greeting : greetings) {
        Greeting patchedGreeting = new Greeting(greeting.data().copy());
        patchedGreeting.setMessage(patchedGreeting.getMessage().toUpperCase());
        PatchRequest<Greeting> patchRequest = PatchGenerator.diff(greeting, patchedGreeting);
        patchedGreetingsDiffs.put(patchedGreeting.getId(), patchRequest);
        patchedGreetings.add(patchedGreeting);
    }
    // Batch patch
    Request<BatchKVResponse<Long, UpdateStatus>> batchUpdateRequest = builders.batchPartialUpdate().patchInputs(patchedGreetingsDiffs).build();
    Map<Long, UpdateStatus> results = getClient().sendRequest(batchUpdateRequest).getResponse().getEntity().getResults();
    Assert.assertEquals(results.size(), patchedGreetingsDiffs.size());
    for (UpdateStatus status : results.values()) {
        Assert.assertEquals(status.getStatus().intValue(), HttpStatus.S_204_NO_CONTENT.getCode());
    }
    getAndVerifyBatchTestDataSerially(builders, createdIds, patchedGreetings, null);
    deleteAndVerifyBatchTestDataSerially(builders, createdIds);
}
Also used : Greeting(com.linkedin.restli.examples.greetings.api.Greeting) UpdateStatus(com.linkedin.restli.common.UpdateStatus) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) PatchRequest(com.linkedin.restli.common.PatchRequest) BatchKVResponse(com.linkedin.restli.client.response.BatchKVResponse) Test(org.testng.annotations.Test)

Aggregations

PatchRequest (com.linkedin.restli.common.PatchRequest)32 HashMap (java.util.HashMap)26 Test (org.testng.annotations.Test)22 Map (java.util.Map)14 Greeting (com.linkedin.restli.examples.greetings.api.Greeting)11 DataMap (com.linkedin.data.DataMap)9 BatchKVResponse (com.linkedin.restli.client.response.BatchKVResponse)8 UpdateStatus (com.linkedin.restli.common.UpdateStatus)6 BatchPatchRequest (com.linkedin.restli.server.BatchPatchRequest)6 ComplexResourceKey (com.linkedin.restli.common.ComplexResourceKey)5 CompoundKey (com.linkedin.restli.common.CompoundKey)5 CustomLong (com.linkedin.restli.examples.custom.types.CustomLong)5 CreateGreeting (com.linkedin.restli.examples.greetings.client.CreateGreeting)5 PartialUpdateGreeting (com.linkedin.restli.examples.greetings.client.PartialUpdateGreeting)5 PartialUpdateGreetingFluentClient (com.linkedin.restli.examples.greetings.client.PartialUpdateGreetingFluentClient)5 ValidationResult (com.linkedin.data.schema.validation.ValidationResult)4 StringMap (com.linkedin.data.template.StringMap)4 KeyValueRecord (com.linkedin.restli.common.KeyValueRecord)4 BatchUpdateResult (com.linkedin.restli.server.BatchUpdateResult)4 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)4