Search in sources :

Example 21 with CollectionMetadata

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

the class TestRestLiResponseHandler method testCollections.

@Test(dataProvider = TestConstants.RESTLI_PROTOCOL_1_2_PREFIX + "basicData")
public void testCollections(AcceptTypeData acceptTypeData, ProtocolVersion protocolVersion, String errorResponseHeaderName) throws Exception {
    ResourceModel resourceModel = buildResourceModel(StatusCollectionResource.class);
    ResourceMethodDescriptor methodDescriptor = resourceModel.findFinderMethod("search");
    RestLiResponse response;
    // #1 check datamap/entity structure
    ServerResourceContext context = new ResourceContextImpl();
    RestUtils.validateRequestHeadersAndUpdateResourceContext(acceptTypeData.acceptHeaders, Collections.emptySet(), context);
    RoutingResult routingResult = new RoutingResult(context, methodDescriptor);
    response = buildPartialRestResponse(buildRequest(acceptTypeData.acceptHeaders, protocolVersion), routingResult, buildStatusList(3));
    checkResponse(response, 200, 1, true, errorResponseHeaderName);
    String baseUri = "/test?someParam=foo";
    // #1.1 using CollectionResult
    response = invokeResponseHandler(baseUri + "&start=0&count=5", methodDescriptor, new BasicCollectionResult<>(buildStatusList(5)), acceptTypeData.acceptHeaders, protocolVersion);
    checkCollectionResponse(response, 5, 0, 5, 1, null, null, null, acceptTypeData);
    // #1.1 using CollectionResult (with total)
    response = invokeResponseHandler(baseUri + "&start=0&count=5", methodDescriptor, new BasicCollectionResult<>(buildStatusList(5), 10), acceptTypeData.acceptHeaders, protocolVersion);
    checkCollectionResponse(response, 5, 0, 5, 1, 10, null, null, acceptTypeData);
    // using CollectionResult with metadata RecordTemplate
    CollectionMetadata metadata = new CollectionMetadata();
    metadata.setCount(42);
    response = invokeResponseHandler(baseUri + "&start=0&count=5", methodDescriptor, new CollectionResult<>(buildStatusList(5), 10, metadata), acceptTypeData.acceptHeaders, protocolVersion);
    checkCollectionResponse(response, 5, 0, 5, 1, 10, null, null, acceptTypeData);
    DataMap dataMap = response.getDataMap();
    CollectionResponse<Status> collectionResponse = new CollectionResponse<>(dataMap, Status.class);
    assertEquals(new CollectionMetadata(collectionResponse.getMetadataRaw()), metadata);
    // #2 pagination: first page, no next
    response = invokeResponseHandler(baseUri + "&start=0&count=5", methodDescriptor, buildStatusList(3), acceptTypeData.acceptHeaders, protocolVersion);
    checkCollectionResponse(response, 3, 0, 5, 0, null, null, null, acceptTypeData);
    // #3 pagination: first page, has next (boundary case)
    response = invokeResponseHandler(baseUri + "&start=0&count=5", methodDescriptor, buildStatusList(5), acceptTypeData.acceptHeaders, protocolVersion);
    // "/test?count=5&start=5&someParam=foo"
    final Map<String, String> queryParamsMap3next = new HashMap<>();
    queryParamsMap3next.put("count", "5");
    queryParamsMap3next.put("start", "5");
    queryParamsMap3next.put("someParam", "foo");
    final URIDetails expectedURIDetails3next = new URIDetails(protocolVersion, "/test", null, queryParamsMap3next, null);
    checkCollectionResponse(response, 5, 0, 5, 1, null, null, expectedURIDetails3next, acceptTypeData);
    // #4 pagination: second page, has prev/ext
    response = invokeResponseHandler(baseUri + "&start=5&count=5", methodDescriptor, buildStatusList(5), acceptTypeData.acceptHeaders, protocolVersion);
    // "/test?count=5&start=0&someParam=foo", "/test?count=5&start=10&someParam=foo",
    final Map<String, String> queryParamsMap4prev = new HashMap<>();
    queryParamsMap4prev.put("count", "5");
    queryParamsMap4prev.put("start", "0");
    queryParamsMap4prev.put("someParam", "foo");
    final URIDetails expectedURIDetails4prev = new URIDetails(protocolVersion, "/test", null, queryParamsMap4prev, null);
    final Map<String, String> queryParamsMap4next = new HashMap<>();
    queryParamsMap4next.put("count", "5");
    queryParamsMap4next.put("start", "10");
    queryParamsMap4next.put("someParam", "foo");
    final URIDetails expectedURIDetails4next = new URIDetails(protocolVersion, "/test", null, queryParamsMap4next, null);
    checkCollectionResponse(response, 5, 5, 5, 2, null, expectedURIDetails4prev, expectedURIDetails4next, acceptTypeData);
    // #5 pagination:last page, has prev
    response = invokeResponseHandler(baseUri + "&start=10&count=5", methodDescriptor, buildStatusList(4), acceptTypeData.acceptHeaders, protocolVersion);
    // "/test?count=5&start=5&someParam=foo"
    final Map<String, String> queryParamsMap5prev = new HashMap<>();
    queryParamsMap5prev.put("count", "5");
    queryParamsMap5prev.put("start", "5");
    queryParamsMap5prev.put("someParam", "foo");
    final URIDetails expectedURIDetails5prev = new URIDetails(protocolVersion, "/test", null, queryParamsMap5prev, null);
    checkCollectionResponse(response, 4, 10, 5, 1, null, expectedURIDetails5prev, null, acceptTypeData);
    response = invokeResponseHandler(baseUri + "&start=10&count=5", methodDescriptor, new BasicCollectionResult<>(buildStatusList(4), 15), acceptTypeData.acceptHeaders, protocolVersion);
    // "/test?count=5&start=5&someParam=foo", "/test?count=5&start=14&someParam=foo"
    final Map<String, String> queryParamsMap6prev = new HashMap<>();
    queryParamsMap6prev.put("count", "5");
    queryParamsMap6prev.put("start", "5");
    queryParamsMap6prev.put("someParam", "foo");
    final URIDetails expectedURIDetails6prev = new URIDetails(protocolVersion, "/test", null, queryParamsMap6prev, null);
    final Map<String, String> queryParamsMap6next = new HashMap<>();
    queryParamsMap6next.put("count", "5");
    queryParamsMap6next.put("start", "14");
    queryParamsMap6next.put("someParam", "foo");
    final URIDetails expectedURIDetails6next = new URIDetails(protocolVersion, "/test", null, queryParamsMap6next, null);
    checkCollectionResponse(response, 4, 10, 5, 2, 15, expectedURIDetails6prev, expectedURIDetails6next, acceptTypeData);
    response = invokeResponseHandler(baseUri + "&start=10&count=5", methodDescriptor, new BasicCollectionResult<>(buildStatusList(4), 14), acceptTypeData.acceptHeaders, protocolVersion);
    // "/test?count=5&start=5&someParam=foo"
    final Map<String, String> queryParamsMap7prev = new HashMap<>();
    queryParamsMap7prev.put("count", "5");
    queryParamsMap7prev.put("start", "5");
    queryParamsMap7prev.put("someParam", "foo");
    final URIDetails expectedURIDetails7prev = new URIDetails(protocolVersion, "/test", null, queryParamsMap7prev, null);
    checkCollectionResponse(response, 4, 10, 5, 1, 14, expectedURIDetails7prev, null, acceptTypeData);
}
Also used : Status(com.linkedin.restli.server.twitter.TwitterTestDataModels.Status) HttpStatus(com.linkedin.restli.common.HttpStatus) CollectionMetadata(com.linkedin.restli.common.CollectionMetadata) URIDetails(com.linkedin.restli.internal.testutils.URIDetails) HashMap(java.util.HashMap) CollectionResponse(com.linkedin.restli.common.CollectionResponse) ResourceMethodDescriptor(com.linkedin.restli.internal.server.model.ResourceMethodDescriptor) RestLiResponse(com.linkedin.restli.internal.server.response.RestLiResponse) ByteString(com.linkedin.data.ByteString) DataMap(com.linkedin.data.DataMap) RoutingResult(com.linkedin.restli.internal.server.RoutingResult) CollectionResult(com.linkedin.restli.server.CollectionResult) BasicCollectionResult(com.linkedin.restli.server.BasicCollectionResult) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) BasicCollectionResult(com.linkedin.restli.server.BasicCollectionResult) ResourceModel(com.linkedin.restli.internal.server.model.ResourceModel) RestLiTestHelper.buildResourceModel(com.linkedin.restli.server.test.RestLiTestHelper.buildResourceModel) ResourceContextImpl(com.linkedin.restli.internal.server.ResourceContextImpl) Test(org.testng.annotations.Test)

Example 22 with CollectionMetadata

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

the class TestDataMapConverter method createTestDataMap.

private DataMap createTestDataMap() {
    CollectionMetadata someRecord = new CollectionMetadata();
    someRecord.setCount(1);
    someRecord.setStart(0);
    someRecord.setTotal(10);
    LinkArray links = new LinkArray();
    Link link = new Link();
    link.setHref("prevUri");
    link.setRel("prev");
    link.setType("en");
    links.add(link);
    someRecord.setLinks(links);
    return someRecord.data();
}
Also used : CollectionMetadata(com.linkedin.restli.common.CollectionMetadata) LinkArray(com.linkedin.restli.common.LinkArray) Link(com.linkedin.restli.common.Link)

Example 23 with CollectionMetadata

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

the class TestRestLiCallback method testOnErrorWithFiltersExceptionFromFirstFilterSecondFilterHandles.

@SuppressWarnings({ "unchecked", "deprecation" })
@Test(dataProvider = "provideResponseEntities")
public void testOnErrorWithFiltersExceptionFromFirstFilterSecondFilterHandles(final ResourceMethod resourceMethod, final RestLiResponseData<?> responseAppData, final Object entityFromFilter2) throws Exception {
    // App stuff.
    RestLiServiceException exFromApp = new RestLiServiceException(HttpStatus.S_404_NOT_FOUND, "App failure");
    // Filter stuff.
    final Exception exFromFirstFilter = new RuntimeException("Runtime exception from first filter");
    final Map<String, String> headersFromFilter = Maps.newHashMap();
    headersFromFilter.put(RestConstants.HEADER_RESTLI_PROTOCOL_VERSION, AllProtocolVersions.LATEST_PROTOCOL_VERSION.toString());
    String errorResponseHeaderName = HeaderUtil.getErrorResponseHeaderName(AllProtocolVersions.LATEST_PROTOCOL_VERSION);
    headersFromFilter.put(errorResponseHeaderName, RestConstants.HEADER_VALUE_ERROR);
    RestLiResponse partialResponse = new RestLiResponse.Builder().build();
    ArgumentCaptor<RestLiServiceException> wrappedExCapture = ArgumentCaptor.forClass(RestLiServiceException.class);
    final String customHeader = "Custom-Header";
    final String customHeaderValue = "CustomValue";
    // Setup.
    when(_responseHandler.buildExceptionResponseData(eq(_routingResult), wrappedExCapture.capture(), anyMap(), anyList())).thenReturn(responseAppData);
    when(_responseHandler.buildPartialResponse(_routingResult, responseAppData)).thenReturn(partialResponse);
    when(_restRequest.getHeaders()).thenReturn(null);
    // Mock filter behavior.
    doAnswer(new Answer<Object>() {

        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            Object[] args = invocation.getArguments();
            FilterRequestContext requestContext = (FilterRequestContext) args[1];
            FilterResponseContext responseContext = (FilterResponseContext) args[2];
            responseContext.getResponseData().getHeaders().putAll(headersFromFilter);
            return completedFutureWithError(exFromFirstFilter);
        }
    }).doAnswer(new Answer<Object>() {

        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            Object[] args = invocation.getArguments();
            FilterRequestContext requestContext = (FilterRequestContext) args[1];
            FilterResponseContext responseContext = (FilterResponseContext) args[2];
            // The second filter should be invoked with details of the exception thrown by the first
            // filter. Verify incoming data.
            assertEquals(responseContext.getResponseData().getStatus(), HttpStatus.S_500_INTERNAL_SERVER_ERROR);
            switch(ResponseTypeUtil.fromMethodType(resourceMethod)) {
                case SINGLE_ENTITY:
                    assertNull(responseContext.getResponseData().getRecordResponseEnvelope().getRecord());
                    break;
                case GET_COLLECTION:
                    assertNull(responseContext.getResponseData().getCollectionResponseEnvelope().getCollectionResponse());
                    break;
                case CREATE_COLLECTION:
                    assertNull(responseContext.getResponseData().getBatchCreateResponseEnvelope().getCreateResponses());
                    break;
                case BATCH_ENTITIES:
                    assertNull(responseContext.getResponseData().getBatchResponseEnvelope().getBatchResponseMap());
                    break;
                case STATUS_ONLY:
                    break;
            }
            assertEquals(responseContext.getResponseData().getHeaders(), headersFromFilter);
            assertTrue(responseContext.getResponseData().isErrorResponse());
            // Modify data.
            responseContext.getResponseData().getHeaders().put(customHeader, customHeaderValue);
            setStatus(responseContext, HttpStatus.S_402_PAYMENT_REQUIRED);
            // filter.
            if (entityFromFilter2 instanceof RecordTemplate) {
                responseContext.getResponseData().getRecordResponseEnvelope().setRecord((RecordTemplate) entityFromFilter2, HttpStatus.S_402_PAYMENT_REQUIRED);
            } else if (entityFromFilter2 instanceof List) {
                responseContext.getResponseData().getCollectionResponseEnvelope().setCollectionResponse((List<? extends RecordTemplate>) entityFromFilter2, new CollectionMetadata(), null, HttpStatus.S_402_PAYMENT_REQUIRED);
            } else {
                Map<Object, BatchResponseEnvelope.BatchResponseEntry> responseMap = new HashMap<>();
                for (Map.Entry<?, RecordTemplate> entry : ((Map<?, RecordTemplate>) entityFromFilter2).entrySet()) {
                    responseMap.put(entry.getKey(), new BatchResponseEnvelope.BatchResponseEntry(HttpStatus.S_200_OK, entry.getValue()));
                }
                responseContext.getResponseData().getBatchResponseEnvelope().setBatchResponseMap(responseMap, HttpStatus.S_402_PAYMENT_REQUIRED);
            }
            return CompletableFuture.completedFuture(null);
        }
    }).when(_filter).onError(any(Throwable.class), eq(_filterRequestContext), any(FilterResponseContext.class));
    // invoke request filters so cursor is in correct place
    when(_filter.onRequest(any(FilterRequestContext.class))).thenReturn(CompletableFuture.completedFuture(null));
    _twoFilterChain.onRequest(_filterRequestContext, _filterResponseContextFactory);
    // Invoke.
    _twoFilterRestLiCallback.onError(exFromApp);
    // Verify.
    verify(_responseHandler).buildExceptionResponseData(eq(_routingResult), wrappedExCapture.capture(), anyMap(), anyList());
    verify(_responseHandler).buildPartialResponse(_routingResult, responseAppData);
    verify(_callback).onSuccess(partialResponse);
    verify(_restRequest).getHeaders();
    verifyNoMoreInteractions(_restRequest, _responseHandler, _callback);
    assertNotNull(responseAppData);
    assertEquals(HttpStatus.S_402_PAYMENT_REQUIRED, responseAppData.getResponseEnvelope().getStatus());
    // Only the error header should have been cleared.
    assertFalse(responseAppData.getHeaders().containsKey(errorResponseHeaderName));
    assertEquals(responseAppData.getHeaders().get(customHeader), customHeaderValue);
    if (entityFromFilter2 instanceof RecordTemplate) {
        assertTrue(responseAppData.getResponseType() == ResponseType.SINGLE_ENTITY);
        assertEquals(responseAppData.getRecordResponseEnvelope().getRecord(), entityFromFilter2);
    } else if (entityFromFilter2 instanceof List) {
        if (responseAppData.getResponseType() == ResponseType.GET_COLLECTION) {
            assertEquals(responseAppData.getCollectionResponseEnvelope().getCollectionResponse(), entityFromFilter2);
        } else {
            fail();
        }
    } else {
        assertTrue(responseAppData.getResponseType() == ResponseType.BATCH_ENTITIES);
        Map<Object, RecordTemplate> values = new HashMap<>();
        for (Map.Entry<?, BatchResponseEnvelope.BatchResponseEntry> entry : responseAppData.getBatchResponseEnvelope().getBatchResponseMap().entrySet()) {
            values.put(entry.getKey(), entry.getValue().getRecord());
        }
        assertEquals(values, entityFromFilter2);
    }
    assertFalse(responseAppData.getResponseEnvelope().isErrorResponse());
    RestLiServiceException restliEx = wrappedExCapture.getAllValues().get(0);
    assertNotNull(restliEx);
    assertEquals(exFromApp.getStatus(), restliEx.getStatus());
    assertEquals(exFromApp.getMessage(), restliEx.getMessage());
}
Also used : HashMap(java.util.HashMap) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RecordTemplate(com.linkedin.data.template.RecordTemplate) List(java.util.List) ArrayList(java.util.ArrayList) Matchers.anyList(org.mockito.Matchers.anyList) FilterRequestContext(com.linkedin.restli.server.filter.FilterRequestContext) CollectionMetadata(com.linkedin.restli.common.CollectionMetadata) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RoutingException(com.linkedin.restli.server.RoutingException) RestException(com.linkedin.r2.message.rest.RestException) Answer(org.mockito.stubbing.Answer) FilterResponseContext(com.linkedin.restli.server.filter.FilterResponseContext) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Map(java.util.Map) Matchers.anyMap(org.mockito.Matchers.anyMap) HashMap(java.util.HashMap) DataMap(com.linkedin.data.DataMap) Test(org.testng.annotations.Test) BeforeTest(org.testng.annotations.BeforeTest)

Example 24 with CollectionMetadata

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

the class TestBatchFinderResponseBuilder method testItemsOrder.

@Test(dataProvider = TestConstants.RESTLI_PROTOCOL_1_2_PREFIX + "testData")
@SuppressWarnings({ "unchecked", "deprecation" })
public void testItemsOrder(List<Criteria> criteria, RestRequest request, Object results, ProtocolVersion protocolVersion, String label) {
    RoutingResult routingResult = getMockRoutingResult(criteria, protocolVersion);
    Map<String, String> headers = ResponseBuilderUtil.getHeaders();
    BatchFinderResponseBuilder responseBuilder = new BatchFinderResponseBuilder(new ErrorResponseBuilder());
    RestLiResponseData<BatchFinderResponseEnvelope> responseData = responseBuilder.buildRestLiResponseData(request, routingResult, results, headers, Collections.emptyList());
    RestLiResponse restResponse = responseBuilder.buildResponse(routingResult, responseData);
    Assert.assertNotNull(restResponse.getEntity());
    Assert.assertEquals(restResponse.getStatus(), HttpStatus.S_200_OK);
    List<BatchFinderResponseEnvelope.BatchFinderEntry> entries = responseData.getResponseEnvelope().getItems();
    assertEquals(entries.size(), criteria.size());
    // check the order is maintained
    for (int i = 0; i < criteria.size(); i++) {
        Foo currentCriteria = criteria.get(i).criteria;
        BatchFinderResponseEnvelope.BatchFinderEntry entry = entries.get(i);
        // If on error, the criteria i should have an exception with the serviceError i
        if (entry.getElements() == null) {
            Assert.assertNotNull(entry.getException());
            Assert.assertEquals(entry.getException().getServiceErrorCode(), currentCriteria.getIntField());
        } else // otherwise, at least the StringField of the first element should be equal to the criteria
        {
            Foo t = new Foo(entry.getElements().get(0).data());
            Assert.assertEquals(t.getStringField(), currentCriteria.getStringField());
            // Check paging
            CollectionMetadata paging = entry.getPaging();
            // If we have less or more elements that the number we asked for, we should not have links
            if (currentCriteria.getIntField() != PAGE_COUNT) {
                Assert.assertTrue(paging.getLinks().size() == 0);
            } else // Check the pagination format and contain only the current criteria
            {
                Assert.assertTrue(paging.getLinks().size() == 1);
                // Only 1 criteria and the criteria that match
                Assert.assertTrue(criteria.get(i).validateLink(paging.getLinks().get(0).getHref(), protocolVersion));
            }
        }
    }
}
Also used : CollectionMetadata(com.linkedin.restli.common.CollectionMetadata) Foo(com.linkedin.pegasus.generator.examples.Foo) RoutingResult(com.linkedin.restli.internal.server.RoutingResult) Test(org.testng.annotations.Test)

Example 25 with CollectionMetadata

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

the class TestMockCollectionResponseFactory method testCreate.

@Test
public void testCreate() {
    Greeting g1 = new Greeting().setId(1L).setMessage("g1");
    Greeting g2 = new Greeting().setId(2L).setMessage("g2");
    List<Greeting> greetings = Arrays.asList(g1, g2);
    CollectionMetadata pagingMetadata = new CollectionMetadata().setCount(2).setStart(0).setTotal(2);
    DataMap customMetadata = new DataMap();
    customMetadata.put("foo", "bar");
    CollectionResponse<Greeting> collectionResponse = MockCollectionResponseFactory.create(Greeting.class, greetings, pagingMetadata, customMetadata);
    Assert.assertEquals(collectionResponse.getElements(), greetings);
    Assert.assertEquals(collectionResponse.getPaging(), pagingMetadata);
    Assert.assertEquals(collectionResponse.getMetadataRaw(), customMetadata);
}
Also used : Greeting(com.linkedin.restli.examples.greetings.api.Greeting) CollectionMetadata(com.linkedin.restli.common.CollectionMetadata) DataMap(com.linkedin.data.DataMap) Test(org.testng.annotations.Test)

Aggregations

CollectionMetadata (com.linkedin.restli.common.CollectionMetadata)30 Test (org.testng.annotations.Test)18 ArrayList (java.util.ArrayList)13 DataMap (com.linkedin.data.DataMap)9 CollectionResponse (com.linkedin.restli.common.CollectionResponse)8 Greeting (com.linkedin.restli.examples.greetings.api.Greeting)8 RecordTemplate (com.linkedin.data.template.RecordTemplate)7 HashMap (java.util.HashMap)7 EmptyRecord (com.linkedin.restli.common.EmptyRecord)6 LinkArray (com.linkedin.restli.common.LinkArray)6 RestLiServiceException (com.linkedin.restli.server.RestLiServiceException)6 List (java.util.List)6 DataProvider (org.testng.annotations.DataProvider)5 Link (com.linkedin.restli.common.Link)4 AnyRecord (com.linkedin.restli.internal.server.methods.AnyRecord)4 HighLevelRecordWithDefault (com.linkedin.restli.examples.defaults.api.HighLevelRecordWithDefault)3 LowLevelRecordWithDefault (com.linkedin.restli.examples.defaults.api.LowLevelRecordWithDefault)3 ResponseType (com.linkedin.restli.internal.server.ResponseType)3 URIDetails (com.linkedin.restli.internal.testutils.URIDetails)3 DataList (com.linkedin.data.DataList)2