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);
}
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 } };
}
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);
}
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);
}
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);
}
Aggregations