Search in sources :

Example 6 with UpdateEntityStatus

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

the class TestBatchPartialUpdateResponseBuilder method testBuilder.

/**
 * Ensures that the response builder can correctly process inputs without any errors. This involves varying result
 * types, status codes, and values of the {@link com.linkedin.restli.common.RestConstants#RETURN_ENTITY_PARAM} query
 * parameter.
 *
 * @param result result object to use as input to this builder.
 * @param isReturnEntityRequested semantic value of the "return entity" query parameter.
 * @param expectedRecords expected records in response data, if any.
 */
@Test(dataProvider = "responseData")
@SuppressWarnings("unchecked")
public void testBuilder(BatchUpdateResult<Long, TestRecord> result, boolean isReturnEntityRequested, Map<?, RecordTemplate> expectedRecords) {
    Map<String, String> headers = ResponseBuilderUtil.getHeaders();
    RoutingResult routingResult = getMockRoutingResult(isReturnEntityRequested, null);
    BatchPartialUpdateResponseBuilder batchPartialUpdateResponseBuilder = new BatchPartialUpdateResponseBuilder(new ErrorResponseBuilder());
    RestLiResponseData<BatchPartialUpdateResponseEnvelope> responseData = batchPartialUpdateResponseBuilder.buildRestLiResponseData(null, routingResult, result, headers, Collections.emptyList());
    RestLiResponse restLiResponse = batchPartialUpdateResponseBuilder.buildResponse(routingResult, responseData);
    ResponseBuilderUtil.validateHeaders(restLiResponse, headers);
    Assert.assertEquals(restLiResponse.getStatus(), HttpStatus.S_200_OK);
    Assert.assertEquals(responseData.getResponseType(), ResponseType.BATCH_ENTITIES);
    Assert.assertEquals(responseData.getResourceMethod(), ResourceMethod.BATCH_PARTIAL_UPDATE);
    Assert.assertEquals(responseData.getResponseEnvelope().getResourceMethod(), ResourceMethod.BATCH_PARTIAL_UPDATE);
    final Map<Long, BatchResponseEnvelope.BatchResponseEntry> batchResponseMap = (Map<Long, BatchResponseEnvelope.BatchResponseEntry>) responseData.getResponseEnvelope().getBatchResponseMap();
    Assert.assertNotNull(batchResponseMap);
    for (Map.Entry<Long, BatchResponseEnvelope.BatchResponseEntry> entry : batchResponseMap.entrySet()) {
        final HttpStatus expectedStatus = result.getResults().get(entry.getKey()).getStatus();
        BatchResponseEnvelope.BatchResponseEntry batchResponseEntry = entry.getValue();
        Assert.assertNotNull(batchResponseEntry);
        Assert.assertFalse(batchResponseEntry.hasException());
        Assert.assertEquals(batchResponseEntry.getStatus(), expectedStatus);
        UpdateStatus updateStatus = (UpdateStatus) batchResponseEntry.getRecord();
        Assert.assertNotNull(updateStatus);
        Assert.assertFalse(updateStatus.hasError());
        Assert.assertEquals(updateStatus.getStatus().intValue(), expectedStatus.getCode());
        if (updateStatus instanceof UpdateEntityStatus) {
            UpdateEntityStatus<TestRecord> updateEntityStatus = (UpdateEntityStatus<TestRecord>) updateStatus;
            Assert.assertEquals(updateEntityStatus.hasEntity(), isReturnEntityRequested);
            // If no entity is to be returned, then these should both be null
            RecordTemplate record = updateEntityStatus.getEntity();
            // can be null
            RecordTemplate expectedRecord = expectedRecords.get(entry.getKey());
            Assert.assertEquals(record, expectedRecord);
        }
    }
}
Also used : UpdateEntityStatus(com.linkedin.restli.common.UpdateEntityStatus) UpdateStatus(com.linkedin.restli.common.UpdateStatus) HttpStatus(com.linkedin.restli.common.HttpStatus) RoutingResult(com.linkedin.restli.internal.server.RoutingResult) RecordTemplate(com.linkedin.data.template.RecordTemplate) HashMap(java.util.HashMap) Map(java.util.Map) TestRecord(com.linkedin.restli.server.TestRecord) Test(org.testng.annotations.Test)

Example 7 with UpdateEntityStatus

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

the class TestBatchPartialUpdateResponseBuilder method testProjectionInBuildRestLiResponseData.

/**
 * Ensures that the returned entities are properly projected when a projection mask is passed into the response builder.
 */
@Test
@SuppressWarnings("unchecked")
public void testProjectionInBuildRestLiResponseData() {
    final Long id = 1L;
    TestRecord record = new TestRecord().setIntField(2147).setDoubleField(21.47).setFloatField(123F).setLongField(456L);
    BatchUpdateEntityResult<Long, TestRecord> result = new BatchUpdateEntityResult<>(Collections.singletonMap(id, new UpdateEntityResponse<>(HttpStatus.S_200_OK, record)));
    MaskTree maskTree = new MaskTree();
    maskTree.addOperation(new PathSpec("intField"), MaskOperation.POSITIVE_MASK_OP);
    Map<String, String> headers = ResponseBuilderUtil.getHeaders();
    RoutingResult routingResult = getMockRoutingResult(true, maskTree);
    BatchPartialUpdateResponseBuilder batchPartialUpdateResponseBuilder = new BatchPartialUpdateResponseBuilder(new ErrorResponseBuilder());
    RestLiResponseData<BatchPartialUpdateResponseEnvelope> responseData = batchPartialUpdateResponseBuilder.buildRestLiResponseData(null, routingResult, result, headers, Collections.emptyList());
    UpdateEntityStatus<TestRecord> updateEntityStatus = (UpdateEntityStatus<TestRecord>) responseData.getResponseEnvelope().getBatchResponseMap().get(id).getRecord();
    Assert.assertNotNull(updateEntityStatus);
    RecordTemplate returnedRecord = updateEntityStatus.getEntity();
    Assert.assertEquals(returnedRecord.data().size(), 1, "Expected response record to be projected down to one field.");
    Assert.assertEquals((int) returnedRecord.data().get("intField"), 2147, "Expected response record intField to match original.");
}
Also used : UpdateEntityStatus(com.linkedin.restli.common.UpdateEntityStatus) BatchUpdateEntityResult(com.linkedin.restli.server.BatchUpdateEntityResult) PathSpec(com.linkedin.data.schema.PathSpec) RoutingResult(com.linkedin.restli.internal.server.RoutingResult) MaskTree(com.linkedin.data.transform.filter.request.MaskTree) UpdateEntityResponse(com.linkedin.restli.server.UpdateEntityResponse) RecordTemplate(com.linkedin.data.template.RecordTemplate) TestRecord(com.linkedin.restli.server.TestRecord) Test(org.testng.annotations.Test)

Example 8 with UpdateEntityStatus

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

the class LatencyInstrumentationResource method create.

/**
 * This is the "upstream endpoint" which is queried directly by the integration test.
 * This endpoint makes a call to {@link #batchPartialUpdate(BatchPatchRequest)} (the "downstream endpoint"),
 * then packs all the client-side timing data into the original server-side request context.
 */
@ReturnEntity
@RestMethod.Create
public CreateKVResponse<Long, InstrumentationControl> create(InstrumentationControl control) {
    final boolean forceException = control.isForceException();
    final boolean useScatterGather = control.isUseScatterGather();
    final String uriPrefix = control.getServiceUriPrefix();
    // Build the downstream request
    final BatchPartialUpdateEntityRequestBuilder<Long, InstrumentationControl> builder = new LatencyInstrumentationBuilders().batchPartialUpdateAndGet();
    final PatchRequest<InstrumentationControl> patch = PatchGenerator.diffEmpty(control);
    for (long i = 0; i < DOWNSTREAM_BATCH_SIZE; i++) {
        builder.input(i, patch);
    }
    final BatchPartialUpdateEntityRequest<Long, InstrumentationControl> request = builder.build();
    // Set up the Rest.li client config
    final RestLiClientConfig clientConfig = new RestLiClientConfig();
    clientConfig.setUseStreaming(control.isUseStreaming());
    if (useScatterGather) {
        clientConfig.setScatterGatherStrategy(new DefaultScatterGatherStrategy(new DummyUriMapper()));
    }
    final TransportClient transportClient = new HttpClientFactory.Builder().build().getClient(Collections.emptyMap());
    final RestClient restClient = new ForceScatterGatherRestClient(new TransportClientAdapter(transportClient), uriPrefix, clientConfig);
    final RequestContext serverRequestContext = getContext().getRawRequestContext();
    final RequestContext clientRequestContext = new RequestContext();
    // Load the timing importance threshold from the server context into the client context
    clientRequestContext.putLocalAttr(TimingContextUtil.TIMING_IMPORTANCE_THRESHOLD_KEY_NAME, serverRequestContext.getLocalAttr(TimingContextUtil.TIMING_IMPORTANCE_THRESHOLD_KEY_NAME));
    try {
        // Make the request, then assert that the returned errors (if any) are as expected
        BatchKVResponse<Long, UpdateEntityStatus<InstrumentationControl>> response = restClient.sendRequest(request, clientRequestContext).getResponseEntity();
        final Map<Long, ErrorResponse> errors = response.getErrors();
        if (forceException && errors.isEmpty()) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Expected failures for the downstream batch request, but found none.");
        }
        if (!forceException && !errors.isEmpty()) {
            throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Expected no failures for the downstream batch request, but found some.");
        }
        for (ErrorResponse errorResponse : errors.values()) {
            if (!DOWNSTREAM_ERROR_CODE.equals(errorResponse.getCode())) {
                throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Encountered a downstream failure with an unexpected or missing error code.");
            }
        }
    } catch (RemoteInvocationException e) {
        throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Downstream failures should be batch entry failures, but encountered a top-level request failure.", e);
    }
    Map<TimingKey, TimingContextUtil.TimingContext> clientTimingsMap = TimingContextUtil.getTimingsMap(clientRequestContext);
    Map<TimingKey, TimingContextUtil.TimingContext> serverTimingsMap = TimingContextUtil.getTimingsMap(serverRequestContext);
    // Load all client timings into the server timings map
    serverTimingsMap.putAll(clientTimingsMap);
    getContext().setResponseHeader(HAS_CLIENT_TIMINGS_HEADER, Boolean.TRUE.toString());
    if (forceException) {
        throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "You wanted me to fail, so I failed.").setCode(UPSTREAM_ERROR_CODE);
    }
    return new CreateKVResponse<>(1L, control);
}
Also used : RestLiClientConfig(com.linkedin.restli.client.util.RestLiClientConfig) BatchPartialUpdateEntityRequestBuilder(com.linkedin.restli.client.BatchPartialUpdateEntityRequestBuilder) InstrumentationControl(com.linkedin.restli.examples.instrumentation.api.InstrumentationControl) DefaultScatterGatherStrategy(com.linkedin.restli.client.DefaultScatterGatherStrategy) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) TimingKey(com.linkedin.r2.message.timing.TimingKey) TransportClientAdapter(com.linkedin.r2.transport.common.bridge.client.TransportClientAdapter) RequestContext(com.linkedin.r2.message.RequestContext) RemoteInvocationException(com.linkedin.r2.RemoteInvocationException) UpdateEntityStatus(com.linkedin.restli.common.UpdateEntityStatus) TransportClient(com.linkedin.r2.transport.common.bridge.client.TransportClient) RestClient(com.linkedin.restli.client.RestClient) LatencyInstrumentationBuilders(com.linkedin.restli.examples.instrumentation.client.LatencyInstrumentationBuilders) ErrorResponse(com.linkedin.restli.common.ErrorResponse) CreateKVResponse(com.linkedin.restli.server.CreateKVResponse) ReturnEntity(com.linkedin.restli.server.annotations.ReturnEntity)

Example 9 with UpdateEntityStatus

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

the class BatchPartialUpdateResponseBuilder method buildUpdateStatus.

/**
 * Defines how to build an update status for batch partial update. If the update response is an {@link UpdateEntityResponse}
 * and the client is requesting the entities to be returned, then build an {@link UpdateEntityStatus} containing the
 * entity to be returned for a given update response.
 * @param resourceContext current resource context
 * @param updateResponse update response returned by the resource method
 * @return update status possibly containing the returned entity
 */
@Override
protected UpdateStatus buildUpdateStatus(ResourceContext resourceContext, UpdateResponse updateResponse) {
    if (updateResponse instanceof UpdateEntityResponse && resourceContext.isReturnEntityRequested()) {
        final RecordTemplate entity = ((UpdateEntityResponse<?>) updateResponse).getEntity();
        final DataMap entityData = entity != null ? entity.data() : null;
        final DataMap projectedData = RestUtils.projectFields(entityData, resourceContext);
        return new UpdateEntityStatus<>(updateResponse.getStatus().getCode(), new AnyRecord(projectedData));
    } else {
        return super.buildUpdateStatus(resourceContext, updateResponse);
    }
}
Also used : UpdateEntityStatus(com.linkedin.restli.common.UpdateEntityStatus) AnyRecord(com.linkedin.restli.internal.server.methods.AnyRecord) UpdateEntityResponse(com.linkedin.restli.server.UpdateEntityResponse) RecordTemplate(com.linkedin.data.template.RecordTemplate) DataMap(com.linkedin.data.DataMap)

Example 10 with UpdateEntityStatus

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

the class TestParseqBasedFluentClientApiWithProjections method testBatchPartialUpdateAndGetWithProjection.

@Test
public void testBatchPartialUpdateAndGetWithProjection() throws Exception {
    PartialUpdateGreeting greetings = new PartialUpdateGreetingFluentClient(_parSeqRestliClient, _parSeqUnitTestHelper.getEngine());
    Map<Long, PatchRequest<Greeting>> inputs = new HashMap<>();
    Greeting original = getGreeting();
    String message = "Edited message: fluent api test partialUpdateAndGet";
    Greeting update = getGreeting(message);
    inputs.put(21L, PatchGenerator.diff(original, update));
    inputs.put(22L, PatchGenerator.diff(original, update));
    CompletionStage<Map<Long, UpdateEntityStatus<Greeting>>> result = greetings.batchPartialUpdateAndGet(inputs, optionalParams -> optionalParams.withMask(mask -> mask.withId().withMessage().withTone()));
    CompletableFuture<Map<Long, UpdateEntityStatus<Greeting>>> future = result.toCompletableFuture();
    Assert.assertNotNull(future.get(5000, TimeUnit.MILLISECONDS));
    Assert.assertEquals(future.get().get(21L).getEntity().getId().longValue(), 21L);
    Assert.assertEquals(future.get().get(21L).getEntity().getMessage(), message);
    Assert.assertEquals(future.get().get(22L).getEntity().getId().longValue(), 22L);
    Assert.assertEquals(future.get().get(22L).getEntity().getMessage(), message);
}
Also used : PagingMetadataProjections(com.linkedin.restli.examples.greetings.client.PagingMetadataProjections) Arrays(java.util.Arrays) RestLiValidationFilter(com.linkedin.restli.server.validation.RestLiValidationFilter) CollectionResponse(com.linkedin.restli.common.CollectionResponse) AutoValidationWithProjectionFluentClient(com.linkedin.restli.examples.greetings.client.AutoValidationWithProjectionFluentClient) Test(org.testng.annotations.Test) PatchGenerator(com.linkedin.restli.client.util.PatchGenerator) EntityResponse(com.linkedin.restli.common.EntityResponse) Map(java.util.Map) CreateIdEntityStatus(com.linkedin.restli.common.CreateIdEntityStatus) CreateIdStatus(com.linkedin.restli.common.CreateIdStatus) BatchfindersFluentClient(com.linkedin.restli.examples.greetings.client.BatchfindersFluentClient) ManualProjections(com.linkedin.restli.examples.greetings.client.ManualProjections) Greetings(com.linkedin.restli.examples.greetings.client.Greetings) BeforeClass(org.testng.annotations.BeforeClass) Set(java.util.Set) ParSeqRestliClientConfigBuilder(com.linkedin.restli.client.ParSeqRestliClientConfigBuilder) CollectionMetadata(com.linkedin.restli.common.CollectionMetadata) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) ParSeqRestliClientBuilder(com.linkedin.restli.client.ParSeqRestliClientBuilder) CreateGreeting(com.linkedin.restli.examples.greetings.client.CreateGreeting) AutoValidationWithProjection(com.linkedin.restli.examples.greetings.client.AutoValidationWithProjection) GreetingsFluentClient(com.linkedin.restli.examples.greetings.client.GreetingsFluentClient) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) com.linkedin.restli.examples.greetings.api.myRecord(com.linkedin.restli.examples.greetings.api.myRecord) PatchRequest(com.linkedin.restli.common.PatchRequest) Assert(org.testng.Assert) UpdateEntityStatus(com.linkedin.restli.common.UpdateEntityStatus) ManualProjectionsFluentClient(com.linkedin.restli.examples.greetings.client.ManualProjectionsFluentClient) RestLiResponseException(com.linkedin.restli.client.RestLiResponseException) Greeting(com.linkedin.restli.examples.greetings.api.Greeting) ParSeqUnitTestHelper(com.linkedin.parseq.ParSeqUnitTestHelper) Tone(com.linkedin.restli.examples.greetings.api.Tone) PartialUpdateGreetingFluentClient(com.linkedin.restli.examples.greetings.client.PartialUpdateGreetingFluentClient) IdEntityResponse(com.linkedin.restli.common.IdEntityResponse) AfterClass(org.testng.annotations.AfterClass) ValidationDemo(com.linkedin.restli.examples.greetings.api.ValidationDemo) BatchFinderCriteriaResult(com.linkedin.restli.common.BatchFinderCriteriaResult) PartialUpdateGreeting(com.linkedin.restli.examples.greetings.client.PartialUpdateGreeting) GreetingCriteria(com.linkedin.restli.examples.greetings.api.GreetingCriteria) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) CreateGreetingFluentClient(com.linkedin.restli.examples.greetings.client.CreateGreetingFluentClient) PagingMetadataProjectionsFluentClient(com.linkedin.restli.examples.greetings.client.PagingMetadataProjectionsFluentClient) ParSeqRestliClient(com.linkedin.restli.client.ParSeqRestliClient) BatchCollectionResponse(com.linkedin.restli.common.BatchCollectionResponse) com.linkedin.restli.examples.greetings.api.myItem(com.linkedin.restli.examples.greetings.api.myItem) Batchfinders(com.linkedin.restli.examples.greetings.client.Batchfinders) Sets(org.testng.collections.Sets) CreateGreeting(com.linkedin.restli.examples.greetings.client.CreateGreeting) Greeting(com.linkedin.restli.examples.greetings.api.Greeting) PartialUpdateGreeting(com.linkedin.restli.examples.greetings.client.PartialUpdateGreeting) HashMap(java.util.HashMap) PartialUpdateGreetingFluentClient(com.linkedin.restli.examples.greetings.client.PartialUpdateGreetingFluentClient) PatchRequest(com.linkedin.restli.common.PatchRequest) Map(java.util.Map) HashMap(java.util.HashMap) PartialUpdateGreeting(com.linkedin.restli.examples.greetings.client.PartialUpdateGreeting) Test(org.testng.annotations.Test)

Aggregations

UpdateEntityStatus (com.linkedin.restli.common.UpdateEntityStatus)13 Test (org.testng.annotations.Test)7 Greeting (com.linkedin.restli.examples.greetings.api.Greeting)6 PartialUpdateGreetingRequestBuilders (com.linkedin.restli.examples.greetings.client.PartialUpdateGreetingRequestBuilders)5 DataMap (com.linkedin.data.DataMap)4 RecordTemplate (com.linkedin.data.template.RecordTemplate)4 BatchKVResponse (com.linkedin.restli.client.response.BatchKVResponse)4 HashMap (java.util.HashMap)4 ErrorResponse (com.linkedin.restli.common.ErrorResponse)3 PatchRequest (com.linkedin.restli.common.PatchRequest)3 RoutingResult (com.linkedin.restli.internal.server.RoutingResult)2 TestRecord (com.linkedin.restli.server.TestRecord)2 Map (java.util.Map)2 PathSpec (com.linkedin.data.schema.PathSpec)1 ValidationResult (com.linkedin.data.schema.validation.ValidationResult)1 MaskTree (com.linkedin.data.transform.filter.request.MaskTree)1 ParSeqUnitTestHelper (com.linkedin.parseq.ParSeqUnitTestHelper)1 RemoteInvocationException (com.linkedin.r2.RemoteInvocationException)1 RequestContext (com.linkedin.r2.message.RequestContext)1 TimingKey (com.linkedin.r2.message.timing.TimingKey)1