Search in sources :

Example 6 with CreateKVResponse

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

the class CreateResponseBuilder method buildRestLiResponseData.

@Override
public RestLiResponseData buildRestLiResponseData(RestRequest request, RoutingResult routingResult, Object result, Map<String, String> headers, List<HttpCookie> cookies) {
    CreateResponse createResponse = (CreateResponse) result;
    if (createResponse.hasError()) {
        RestLiResponseDataImpl responseData = new RestLiResponseDataImpl(createResponse.getError(), headers, cookies);
        responseData.setResponseEnvelope(new CreateResponseEnvelope(null, responseData));
        return responseData;
    }
    Object id = null;
    if (createResponse.hasId()) {
        id = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(createResponse.getId(), routingResult);
        final ProtocolVersion protocolVersion = ((ServerResourceContext) routingResult.getContext()).getRestliProtocolVersion();
        String stringKey = URIParamUtils.encodeKeyForUri(id, UriComponent.Type.PATH_SEGMENT, protocolVersion);
        UriBuilder uribuilder = UriBuilder.fromUri(request.getURI());
        uribuilder.path(stringKey);
        if (routingResult.getContext().hasParameter(RestConstants.ALT_KEY_PARAM)) {
            // add altkey param to location URI
            uribuilder.queryParam(RestConstants.ALT_KEY_PARAM, routingResult.getContext().getParameter(RestConstants.ALT_KEY_PARAM));
        }
        headers.put(RestConstants.HEADER_LOCATION, uribuilder.build((Object) null).toString());
        headers.put(HeaderUtil.getIdHeaderName(protocolVersion), URIParamUtils.encodeKeyForHeader(id, protocolVersion));
    }
    //Verify that a null status was not passed into the CreateResponse. If so, this is a developer error.
    if (createResponse.getStatus() == null) {
        throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. HttpStatus is null inside of a CreateResponse from the resource method: " + routingResult.getResourceMethod());
    }
    RestLiResponseDataImpl responseData = new RestLiResponseDataImpl(createResponse.getStatus(), headers, cookies);
    CreateResponseEnvelope responseEnvelope;
    if (createResponse instanceof CreateKVResponse) {
        final ResourceContext resourceContext = routingResult.getContext();
        DataMap entityData = ((CreateKVResponse) createResponse).getEntity().data();
        final DataMap data = RestUtils.projectFields(entityData, resourceContext.getProjectionMode(), resourceContext.getProjectionMask());
        responseEnvelope = new CreateResponseEnvelope(new AnyRecord(data), true, responseData);
    } else //Instance of idResponse
    {
        IdResponse<?> idResponse = new IdResponse<Object>(id);
        responseEnvelope = new CreateResponseEnvelope(idResponse, responseData);
    }
    responseData.setResponseEnvelope(responseEnvelope);
    return responseData;
}
Also used : IdResponse(com.linkedin.restli.common.IdResponse) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) ResourceContext(com.linkedin.restli.server.ResourceContext) AnyRecord(com.linkedin.restli.internal.server.methods.AnyRecord) CreateResponse(com.linkedin.restli.server.CreateResponse) ProtocolVersion(com.linkedin.restli.common.ProtocolVersion) DataMap(com.linkedin.data.DataMap) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) UriBuilder(com.linkedin.jersey.api.uri.UriBuilder) CreateKVResponse(com.linkedin.restli.server.CreateKVResponse)

Example 7 with CreateKVResponse

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

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

the class AutomaticValidationDemoResource method batchCreate.

@RestMethod.BatchCreate
@ReturnEntity
public BatchCreateKVResult<Integer, ValidationDemo> batchCreate(final BatchCreateRequest<Integer, ValidationDemo> entities) {
    List<CreateKVResponse<Integer, ValidationDemo>> results = new ArrayList<>();
    int id = 0;
    for (ValidationDemo entity : entities.getInput()) {
        ValidationDemo returnEntity;
        if (entity.getStringB().equals("b1")) {
            // Missing union field.
            returnEntity = new ValidationDemo().setStringA("a").setStringB("b");
        } else if (entity.getStringB().equals("b2")) {
            // Missing foo1 in myRecord.
            ValidationDemo.UnionFieldWithInlineRecord unionField = new ValidationDemo.UnionFieldWithInlineRecord();
            unionField.setMyRecord(new myRecord().setFoo2(2));
            returnEntity = new ValidationDemo().setStringA("a").setStringB("b").setUnionFieldWithInlineRecord(unionField);
        } else {
            returnEntity = _validReturnEntity;
        }
        results.add(new CreateKVResponse<>(id, returnEntity));
        id++;
    }
    return new BatchCreateKVResult<>(results);
}
Also used : com.linkedin.restli.examples.greetings.api.myRecord(com.linkedin.restli.examples.greetings.api.myRecord) ArrayList(java.util.ArrayList) BatchCreateKVResult(com.linkedin.restli.server.BatchCreateKVResult) CreateKVResponse(com.linkedin.restli.server.CreateKVResponse) ValidationDemo(com.linkedin.restli.examples.greetings.api.ValidationDemo) ReturnEntity(com.linkedin.restli.server.annotations.ReturnEntity)

Example 9 with CreateKVResponse

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

the class CreateGreetingResource method batchCreate.

@ReturnEntity
@RestMethod.BatchCreate
public BatchCreateKVResult<Long, Greeting> batchCreate(BatchCreateRequest<Long, Greeting> entities) {
    List<CreateKVResponse<Long, Greeting>> responses = new ArrayList<>(entities.getInput().size());
    // Maximum number of batch create entity is 3 in this resource. If more than 3 elements are detected, a 400 HTTP exception will be encoded
    int quota = 3;
    for (Greeting greeting : entities.getInput()) {
        if (quota-- <= 0) {
            responses.add(new CreateKVResponse<>(new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "exceed quota")));
        } else {
            responses.add(create(greeting));
        }
    }
    return new BatchCreateKVResult<>(responses);
}
Also used : Greeting(com.linkedin.restli.examples.greetings.api.Greeting) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) ArrayList(java.util.ArrayList) BatchCreateKVResult(com.linkedin.restli.server.BatchCreateKVResult) CreateKVResponse(com.linkedin.restli.server.CreateKVResponse) ReturnEntity(com.linkedin.restli.server.annotations.ReturnEntity)

Example 10 with CreateKVResponse

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

the class TestBatchCreateResponseBuilder method testCreateKVResultBuilder.

@Test(dataProvider = "createKVResultBuilderTestData")
public void testCreateKVResultBuilder(String altKeyName, Map<String, AlternativeKey<?, ?>> alternativeKeyMap, List<CreateIdEntityStatus<?, Foo>> expectedResponses) throws URISyntaxException {
    List<CreateKVResponse<Long, Foo>> createKVResponses = new ArrayList<>(2);
    Foo foo1 = new Foo();
    foo1.setStringField("foo1");
    Foo foo2 = new Foo();
    foo2.setStringField("foo2");
    createKVResponses.add(new CreateKVResponse<>(1L, foo1));
    createKVResponses.add(new CreateKVResponse<>(2L, foo2));
    BatchCreateKVResult<Long, Foo> results = new BatchCreateKVResult<>(createKVResponses);
    Map<String, String> headers = ResponseBuilderUtil.getHeaders();
    ResourceMethodDescriptor mockDescriptor = getMockResourceMethodDescriptor(alternativeKeyMap);
    ServerResourceContext mockContext = getMockKVResourceContext(altKeyName);
    RoutingResult routingResult = new RoutingResult(mockContext, mockDescriptor);
    BatchCreateResponseBuilder responseBuilder = new BatchCreateResponseBuilder(null);
    RestRequest request = new RestRequestBuilder(new URI("/foo")).build();
    RestLiResponseData<BatchCreateResponseEnvelope> responseData = responseBuilder.buildRestLiResponseData(request, routingResult, results, headers, Collections.emptyList());
    RestLiResponse restResponse = responseBuilder.buildResponse(routingResult, responseData);
    EasyMock.verify(mockDescriptor);
    ResponseBuilderUtil.validateHeaders(restResponse, headers);
    Assert.assertTrue(responseData.getResponseEnvelope().isGetAfterCreate());
    List<CreateIdEntityStatus<Object, Foo>> items = new ArrayList<>();
    for (BatchCreateResponseEnvelope.CollectionCreateResponseItem item : responseData.getResponseEnvelope().getCreateResponses()) {
        @SuppressWarnings("unchecked") CreateIdEntityStatus<Object, Foo> record = (CreateIdEntityStatus<Object, Foo>) item.getRecord();
        items.add(record);
    }
    Assert.assertEquals(items, expectedResponses);
    Assert.assertEquals(restResponse.getStatus(), HttpStatus.S_200_OK);
}
Also used : ResourceMethodDescriptor(com.linkedin.restli.internal.server.model.ResourceMethodDescriptor) ArrayList(java.util.ArrayList) URI(java.net.URI) RoutingResult(com.linkedin.restli.internal.server.RoutingResult) CreateIdEntityStatus(com.linkedin.restli.common.CreateIdEntityStatus) Foo(com.linkedin.pegasus.generator.examples.Foo) RestRequest(com.linkedin.r2.message.rest.RestRequest) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) BatchCreateKVResult(com.linkedin.restli.server.BatchCreateKVResult) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) CreateKVResponse(com.linkedin.restli.server.CreateKVResponse) Test(org.testng.annotations.Test)

Aggregations

CreateKVResponse (com.linkedin.restli.server.CreateKVResponse)13 Foo (com.linkedin.pegasus.generator.examples.Foo)7 ServerResourceContext (com.linkedin.restli.internal.server.ServerResourceContext)6 BatchCreateKVResult (com.linkedin.restli.server.BatchCreateKVResult)6 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)6 ArrayList (java.util.ArrayList)6 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)5 RoutingResult (com.linkedin.restli.internal.server.RoutingResult)5 CreateResponse (com.linkedin.restli.server.CreateResponse)5 URI (java.net.URI)5 Test (org.testng.annotations.Test)5 DataMap (com.linkedin.data.DataMap)4 RecordTemplate (com.linkedin.data.template.RecordTemplate)4 PathSpec (com.linkedin.data.schema.PathSpec)3 MaskTree (com.linkedin.data.transform.filter.request.MaskTree)3 RequestContext (com.linkedin.r2.message.RequestContext)3 CreateIdEntityStatus (com.linkedin.restli.common.CreateIdEntityStatus)3 AnyRecord (com.linkedin.restli.internal.server.methods.AnyRecord)3 ReturnEntity (com.linkedin.restli.server.annotations.ReturnEntity)3 UriBuilder (com.linkedin.jersey.api.uri.UriBuilder)2