diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java index 05312b04b6..fb6ded866a 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEntityViewControllerTest.java @@ -17,8 +17,13 @@ package org.thingsboard.server.controller; import com.datastax.oss.driver.api.core.uuid.Uuids; import com.fasterxml.jackson.core.type.TypeReference; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; +import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; import org.eclipse.paho.client.mqttv3.MqttAsyncClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttMessage; @@ -27,7 +32,10 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.ResultActions; +import org.thingsboard.common.util.ThingsBoardExecutors; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityView; @@ -43,20 +51,21 @@ import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.queue.memory.InMemoryStorage; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.TimeUnit; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; @@ -65,17 +74,27 @@ import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; }) @Slf4j public abstract class BaseEntityViewControllerTest extends AbstractControllerTest { + static final int TIMEOUT = 30; + static final TypeReference> PAGE_DATA_ENTITY_VIEW_TYPE_REF = new TypeReference<>() { + }; - private IdComparator idComparator; private Tenant savedTenant; private User tenantAdmin; private Device testDevice; private TelemetryEntityView telemetry; + List> deleteFutures = new ArrayList<>(); + ListeningExecutorService executor; + + @Autowired + InMemoryStorage inMemoryStorage; + @Before public void beforeTest() throws Exception { + log.warn("beforeTest"); + executor = MoreExecutors.listeningDecorator(ThingsBoardExecutors.newWorkStealingPool(16, getClass())); + loginSysAdmin(); - idComparator = new IdComparator<>(); savedTenant = doPost("/api/tenant", getNewTenant("My tenant"), Tenant.class); Assert.assertNotNull(savedTenant); @@ -94,19 +113,22 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes testDevice = doPost("/api/device", device, Device.class); telemetry = new TelemetryEntityView( - Arrays.asList("tsKey1", "tsKey2", "tsKey3"), + List.of("tsKey1", "tsKey2", "tsKey3"), new AttributesEntityView( - Arrays.asList("caKey1", "caKey2", "caKey3", "caKey4"), - Arrays.asList("saKey1", "saKey2", "saKey3", "saKey4"), - Arrays.asList("shKey1", "shKey2", "shKey3", "shKey4"))); + List.of("caKey1", "caKey2", "caKey3", "caKey4"), + List.of("saKey1", "saKey2", "saKey3", "saKey4"), + List.of("shKey1", "shKey2", "shKey3", "shKey4"))); } @After public void afterTest() throws Exception { + executor.shutdownNow(); + loginSysAdmin(); doDelete("/api/tenant/" + savedTenant.getId().getId().toString()) .andExpect(status().isOk()); + log.warn("after test"); } @Test @@ -244,21 +266,18 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes CustomerId customerId = customer.getId(); String urlTemplate = "/api/customer/" + customerId.getId().toString() + "/entityViewInfos?"; - List views = new ArrayList<>(); + List> viewFutures = new ArrayList<>(128); for (int i = 0; i < 128; i++) { - views.add( + String entityName = "Test entity view " + i; + viewFutures.add(executor.submit(() -> new EntityViewInfo(doPost("/api/customer/" + customerId.getId().toString() + "/entityView/" - + getNewSavedEntityView("Test entity view " + i).getId().getId().toString(), EntityView.class), - customer.getTitle(), customer.isPublic()) - ); + + getNewSavedEntityView(entityName).getId().getId().toString(), EntityView.class), + customer.getTitle(), customer.isPublic()))); } - + List entityViewInfos = Futures.allAsList(viewFutures).get(TIMEOUT, SECONDS); List loadedViews = loadListOfInfo(new PageLink(23), urlTemplate); - Collections.sort(views, idComparator); - Collections.sort(loadedViews, idComparator); - - assertEquals(views, loadedViews); + assertThat(entityViewInfos).containsExactlyInAnyOrderElementsOf(loadedViews); } @Test @@ -267,33 +286,37 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes String urlTemplate = "/api/customer/" + customerId.getId().toString() + "/entityViews?"; String name1 = "Entity view name1"; - List namesOfView1 = fillListOf(125, name1, "/api/customer/" + customerId.getId().toString() - + "/entityView/"); + List namesOfView1 = Futures.allAsList(fillListByTemplate(125, name1, "/api/customer/" + customerId.getId().toString() + + "/entityView/")).get(TIMEOUT, SECONDS); List loadedNamesOfView1 = loadListOf(new PageLink(15, 0, name1), urlTemplate); - Collections.sort(namesOfView1, idComparator); - Collections.sort(loadedNamesOfView1, idComparator); - assertEquals(namesOfView1, loadedNamesOfView1); + assertThat(namesOfView1).as(name1).containsExactlyInAnyOrderElementsOf(loadedNamesOfView1); String name2 = "Entity view name2"; - List NamesOfView2 = fillListOf(143, name2, "/api/customer/" + customerId.getId().toString() - + "/entityView/"); + List namesOfView2 = Futures.allAsList(fillListByTemplate(143, name2, "/api/customer/" + customerId.getId().toString() + + "/entityView/")).get(TIMEOUT, SECONDS); List loadedNamesOfView2 = loadListOf(new PageLink(4, 0, name2), urlTemplate); - Collections.sort(NamesOfView2, idComparator); - Collections.sort(loadedNamesOfView2, idComparator); - assertEquals(NamesOfView2, loadedNamesOfView2); + assertThat(namesOfView2).as(name2).containsExactlyInAnyOrderElementsOf(loadedNamesOfView2); + deleteFutures.clear(); for (EntityView view : loadedNamesOfView1) { - doDelete("/api/customer/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); + deleteFutures.add(executor.submit(() -> + doDelete("/api/customer/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()))); } + Futures.allAsList(deleteFutures).get(TIMEOUT, SECONDS); + PageData pageData = doGetTypedWithPageLink(urlTemplate, new TypeReference>() { }, new PageLink(4, 0, name1)); Assert.assertFalse(pageData.hasNext()); assertEquals(0, pageData.getData().size()); + deleteFutures.clear(); for (EntityView view : loadedNamesOfView2) { - doDelete("/api/customer/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); + deleteFutures.add(executor.submit(() -> + doDelete("/api/customer/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()))); } + Futures.allAsList(deleteFutures).get(TIMEOUT, SECONDS); + pageData = doGetTypedWithPageLink(urlTemplate, new TypeReference>() { }, new PageLink(4, 0, name2)); @@ -303,49 +326,52 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes @Test public void testGetTenantEntityViews() throws Exception { - - List views = new ArrayList<>(); + List> entityViewInfoFutures = new ArrayList<>(178); for (int i = 0; i < 178; i++) { - views.add(new EntityViewInfo(getNewSavedEntityView("Test entity view" + i), null, false)); + ListenableFuture entityViewFuture = getNewSavedEntityViewAsync("Test entity view" + i); + entityViewInfoFutures.add(Futures.transform(entityViewFuture, + view -> new EntityViewInfo(view, null, false), + MoreExecutors.directExecutor())); } + List entityViewInfos = Futures.allAsList(entityViewInfoFutures).get(TIMEOUT, SECONDS); List loadedViews = loadListOfInfo(new PageLink(23), "/api/tenant/entityViewInfos?"); - - Collections.sort(views, idComparator); - Collections.sort(loadedViews, idComparator); - - assertEquals(views, loadedViews); + assertThat(entityViewInfos).containsExactlyInAnyOrderElementsOf(loadedViews); } @Test public void testGetTenantEntityViewsByName() throws Exception { String name1 = "Entity view name1"; - List namesOfView1 = fillListOf(143, name1); + List namesOfView1 = Futures.allAsList(fillListOf(143, name1)).get(TIMEOUT, SECONDS); List loadedNamesOfView1 = loadListOf(new PageLink(15, 0, name1), "/api/tenant/entityViews?"); - Collections.sort(namesOfView1, idComparator); - Collections.sort(loadedNamesOfView1, idComparator); - assertEquals(namesOfView1, loadedNamesOfView1); + assertThat(namesOfView1).as(name1).containsExactlyInAnyOrderElementsOf(loadedNamesOfView1); String name2 = "Entity view name2"; - List NamesOfView2 = fillListOf(75, name2); + List namesOfView2 = Futures.allAsList(fillListOf(75, name2)).get(TIMEOUT, SECONDS); + ; List loadedNamesOfView2 = loadListOf(new PageLink(4, 0, name2), "/api/tenant/entityViews?"); - Collections.sort(NamesOfView2, idComparator); - Collections.sort(loadedNamesOfView2, idComparator); - assertEquals(NamesOfView2, loadedNamesOfView2); + assertThat(namesOfView2).as(name2).containsExactlyInAnyOrderElementsOf(loadedNamesOfView2); + deleteFutures.clear(); for (EntityView view : loadedNamesOfView1) { - doDelete("/api/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); + deleteFutures.add(executor.submit(() -> + doDelete("/api/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()))); } + Futures.allAsList(deleteFutures).get(TIMEOUT, SECONDS); + PageData pageData = doGetTypedWithPageLink("/api/tenant/entityViews?", new TypeReference>() { }, new PageLink(4, 0, name1)); Assert.assertFalse(pageData.hasNext()); assertEquals(0, pageData.getData().size()); + deleteFutures.clear(); for (EntityView view : loadedNamesOfView2) { - doDelete("/api/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()); + deleteFutures.add(executor.submit(() -> + doDelete("/api/entityView/" + view.getId().getId().toString()).andExpect(status().isOk()))); } - pageData = doGetTypedWithPageLink("/api/tenant/entityViews?", new TypeReference>() { - }, + Futures.allAsList(deleteFutures).get(TIMEOUT, SECONDS); + + pageData = doGetTypedWithPageLink("/api/tenant/entityViews?", PAGE_DATA_ENTITY_VIEW_TYPE_REF, new PageLink(4, 0, name2)); Assert.assertFalse(pageData.hasNext()); assertEquals(0, pageData.getData().size()); @@ -353,20 +379,22 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes @Test public void testTheCopyOfAttrsIntoTSForTheView() throws Exception { + Set expectedActualAttributesSet = Set.of("caKey1", "caKey2", "caKey3", "caKey4"); Set actualAttributesSet = - getAttributesByKeys("{\"caKey1\":\"value1\", \"caKey2\":true, \"caKey3\":42.0, \"caKey4\":73}"); - - Set expectedActualAttributesSet = - new HashSet<>(Arrays.asList("caKey1", "caKey2", "caKey3", "caKey4")); - assertTrue(actualAttributesSet.containsAll(expectedActualAttributesSet)); + getAttributesByKeys("{\"caKey1\":\"value1\", \"caKey2\":true, \"caKey3\":42.0, \"caKey4\":73}", expectedActualAttributesSet); + log.warn("got correct actualAttributesSet, saving new entity view..."); EntityView savedView = getNewSavedEntityView("Test entity view"); - Thread.sleep(1000); - - List> values = doGetAsyncTyped("/api/plugins/telemetry/ENTITY_VIEW/" + savedView.getId().getId().toString() + - "/values/attributes?keys=" + String.join(",", actualAttributesSet), new TypeReference<>() {}); + log.warn("fetching entity view telemetry..."); + List> values = await("telemetry/ENTITY_VIEW") + .atMost(TIMEOUT, SECONDS) + .until(() -> doGetAsyncTyped("/api/plugins/telemetry/ENTITY_VIEW/" + savedView.getId().getId().toString() + + "/values/attributes?keys=" + String.join(",", actualAttributesSet), new TypeReference<>() { + }), + x -> x.size() >= expectedActualAttributesSet.size()); + log.warn("asserting..."); assertEquals("value1", getValue(values, "caKey1")); assertEquals(true, getValue(values, "caKey2")); assertEquals(42.0, getValue(values, "caKey3")); @@ -375,14 +403,13 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes @Test public void testTheCopyOfAttrsOutOfTSForTheView() throws Exception { + Set expectedActualAttributesSet = Set.of("caKey1", "caKey2", "caKey3", "caKey4"); Set actualAttributesSet = - getAttributesByKeys("{\"caKey1\":\"value1\", \"caKey2\":true, \"caKey3\":42.0, \"caKey4\":73}"); - - Set expectedActualAttributesSet = new HashSet<>(Arrays.asList("caKey1", "caKey2", "caKey3", "caKey4")); - assertTrue(actualAttributesSet.containsAll(expectedActualAttributesSet)); + getAttributesByKeys("{\"caKey1\":\"value1\", \"caKey2\":true, \"caKey3\":42.0, \"caKey4\":73}", expectedActualAttributesSet); List> valueTelemetryOfDevices = doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + testDevice.getId().getId().toString() + - "/values/attributes?keys=" + String.join(",", actualAttributesSet), new TypeReference<>() {}); + "/values/attributes?keys=" + String.join(",", actualAttributesSet), new TypeReference<>() { + }); EntityView view = new EntityView(); view.setEntityId(testDevice.getId()); @@ -394,10 +421,9 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes view.setEndTimeMs((long) getValue(valueTelemetryOfDevices, "lastActivityTime") / 10); EntityView savedView = doPost("/api/entityView", view, EntityView.class); - Thread.sleep(1000); - List> values = doGetAsyncTyped("/api/plugins/telemetry/ENTITY_VIEW/" + savedView.getId().getId().toString() + - "/values/attributes?keys=" + String.join(",", actualAttributesSet), new TypeReference<>() {}); + "/values/attributes?keys=" + String.join(",", actualAttributesSet), new TypeReference<>() { + }); assertEquals(0, values.size()); } @@ -433,6 +459,7 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes } private void uploadTelemetry(String strKvs) throws Exception { + String viewDeviceId = testDevice.getId().getId().toString(); DeviceCredentials deviceCredentials = doGet("/api/device/" + viewDeviceId + "/credentials", DeviceCredentials.class); @@ -447,34 +474,36 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(accessToken); client.connect(options); - awaitConnected(client, TimeUnit.SECONDS.toMillis(30)); + awaitConnected(client, SECONDS.toMillis(30)); MqttMessage message = new MqttMessage(); message.setPayload(strKvs.getBytes()); - client.publish("v1/devices/me/telemetry", message); - Thread.sleep(1000); + IMqttDeliveryToken token = client.publish("v1/devices/me/telemetry", message); + await("mqtt ack").pollInterval(10, MILLISECONDS).atMost(TIMEOUT, SECONDS).until(() -> token.getMessage() == null); client.disconnect(); } private void awaitConnected(MqttAsyncClient client, long ms) throws InterruptedException { - long start = System.currentTimeMillis(); - while (!client.isConnected()) { - Thread.sleep(100); - if (start + ms < System.currentTimeMillis()) { - throw new RuntimeException("Client is not connected!"); - } - } + await("awaitConnected").pollInterval(5, MILLISECONDS).atMost(TIMEOUT, SECONDS) + .until(client::isConnected); } private Set getTelemetryKeys(String type, String id) throws Exception { - return new HashSet<>(doGetAsyncTyped("/api/plugins/telemetry/" + type + "/" + id + "/keys/timeseries", new TypeReference<>() {})); + return new HashSet<>(doGetAsyncTyped("/api/plugins/telemetry/" + type + "/" + id + "/keys/timeseries", new TypeReference<>() { + })); + } + + private Set getAttributeKeys(String type, String id) throws Exception { + return new HashSet<>(doGetAsyncTyped("/api/plugins/telemetry/" + type + "/" + id + "/keys/attributes", new TypeReference<>() { + })); } private Map>> getTelemetryValues(String type, String id, Set keys, Long startTs, Long endTs) throws Exception { return doGetAsyncTyped("/api/plugins/telemetry/" + type + "/" + id + - "/values/timeseries?keys=" + String.join(",", keys) + "&startTs=" + startTs + "&endTs=" + endTs, new TypeReference<>() {}); + "/values/timeseries?keys=" + String.join(",", keys) + "&startTs=" + startTs + "&endTs=" + endTs, new TypeReference<>() { + }); } - private Set getAttributesByKeys(String stringKV) throws Exception { + private Set getAttributesByKeys(String stringKV, Set expectedKeySet) throws Exception { String viewDeviceId = testDevice.getId().getId().toString(); DeviceCredentials deviceCredentials = doGet("/api/device/" + viewDeviceId + "/credentials", DeviceCredentials.class); @@ -489,14 +518,22 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes MqttConnectOptions options = new MqttConnectOptions(); options.setUserName(accessToken); client.connect(options); - awaitConnected(client, TimeUnit.SECONDS.toMillis(30)); + awaitConnected(client, SECONDS.toMillis(30)); MqttMessage message = new MqttMessage(); message.setPayload((stringKV).getBytes()); - client.publish("v1/devices/me/attributes", message); - Thread.sleep(1000); + IMqttDeliveryToken token = client.publish("v1/devices/me/attributes", message); + log.warn("token.message {}", token.getMessage()); + await("mqtt ack").pollInterval(10, MILLISECONDS).atMost(TIMEOUT, SECONDS).until(() -> token.getMessage() == null); + log.warn("token.message delivered {}", token.getMessage()); client.disconnect(); - return new HashSet<>(doGetAsyncTyped("/api/plugins/telemetry/DEVICE/" + viewDeviceId + "/keys/attributes", new TypeReference<>() {})); + + return await().pollInterval(20, MILLISECONDS).atMost(TIMEOUT, SECONDS) + .until(() -> { + inMemoryStorage.printStats(); + return getAttributeKeys("DEVICE", viewDeviceId); + }, + keys -> keys.containsAll(expectedKeySet)); } private Object getValue(List> values, String stringValue) { @@ -506,11 +543,15 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes .findFirst().get().get("value"); } - private EntityView getNewSavedEntityView(String name) throws Exception { + private EntityView getNewSavedEntityView(String name) { EntityView view = createEntityView(name, 0, 0); return doPost("/api/entityView", view, EntityView.class); } + private ListenableFuture getNewSavedEntityViewAsync(String name) { + return executor.submit(() -> getNewSavedEntityView(name)); + } + private EntityView createEntityView(String name, long startTimeMs, long endTimeMs) { EntityView view = new EntityView(); view.setEntityId(testDevice.getId()); @@ -535,33 +576,41 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes return tenant; } - private List fillListOf(int limit, String partOfName, String urlTemplate) throws Exception { - List views = new ArrayList<>(); - for (EntityView view : fillListOf(limit, partOfName)) { - views.add(doPost(urlTemplate + view.getId().getId().toString(), EntityView.class)); + private List> fillListByTemplate(int limit, String partOfName, String urlTemplate) { + List> futures = new ArrayList<>(limit); + for (ListenableFuture viewFuture : fillListOf(limit, partOfName)) { + futures.add(Futures.transform(viewFuture, view -> + doPost(urlTemplate + view.getId().getId().toString(), EntityView.class), + MoreExecutors.directExecutor())); } - return views; + return futures; } - private List fillListOf(int limit, String partOfName) throws Exception { - List viewNames = new ArrayList<>(); + private List> fillListOf(int limit, String partOfName) { + List> viewNameFutures = new ArrayList<>(limit); for (int i = 0; i < limit; i++) { - String fullName = partOfName + ' ' + RandomStringUtils.randomAlphanumeric(15); - fullName = i % 2 == 0 ? fullName.toLowerCase() : fullName.toUpperCase(); - EntityView view = getNewSavedEntityView(fullName); - Customer customer = getNewCustomer("Test customer " + String.valueOf(Math.random())); - view.setCustomerId(doPost("/api/customer", customer, Customer.class).getId()); - viewNames.add(doPost("/api/entityView", view, EntityView.class)); + boolean even = i % 2 == 0; + ListenableFuture customerFuture = executor.submit(() -> { + Customer customer = getNewCustomer("Test customer " + Math.random()); + return doPost("/api/customer", customer, Customer.class).getId(); + }); + + viewNameFutures.add(Futures.transform(customerFuture, customerId -> { + String fullName = partOfName + ' ' + RandomStringUtils.randomAlphanumeric(15); + fullName = even ? fullName.toLowerCase() : fullName.toUpperCase(); + EntityView view = getNewSavedEntityView(fullName); + view.setCustomerId(customerId); + return doPost("/api/entityView", view, EntityView.class); + }, MoreExecutors.directExecutor())); } - return viewNames; + return viewNameFutures; } private List loadListOf(PageLink pageLink, String urlTemplate) throws Exception { List loadedItems = new ArrayList<>(); PageData pageData; do { - pageData = doGetTypedWithPageLink(urlTemplate, new TypeReference>() { - }, pageLink); + pageData = doGetTypedWithPageLink(urlTemplate, PAGE_DATA_ENTITY_VIEW_TYPE_REF, pageLink); loadedItems.addAll(pageData.getData()); if (pageData.hasNext()) { pageLink = pageLink.nextPageLink(); @@ -600,7 +649,7 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class); PageData pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/entityViews?", - new TypeReference>() {}, new PageLink(100)); + PAGE_DATA_ENTITY_VIEW_TYPE_REF, new PageLink(100)); Assert.assertEquals(1, pageData.getData().size()); @@ -608,7 +657,7 @@ public abstract class BaseEntityViewControllerTest extends AbstractControllerTes + "/entityView/" + savedEntityView.getId().getId().toString(), EntityView.class); pageData = doGetTypedWithPageLink("/api/edge/" + savedEdge.getId().getId().toString() + "/entityViews?", - new TypeReference>() {}, new PageLink(100)); + PAGE_DATA_ENTITY_VIEW_TYPE_REF, new PageLink(100)); Assert.assertEquals(0, pageData.getData().size()); }