diff --git a/common/pom.xml b/common/pom.xml
index 5392bfe4..1cb156e6 100644
--- a/common/pom.xml
+++ b/common/pom.xml
@@ -127,6 +127,18 @@
junit-jupiter
+
+ org.mockito
+ mockito-core
+ ${version.org.mockito.mockito-junit-jupiter}
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ test
+
+
io.github.resilience4j
resilience4j-retry
diff --git a/common/src/main/java/org/fiware/tmforum/common/repository/TmForumRepository.java b/common/src/main/java/org/fiware/tmforum/common/repository/TmForumRepository.java
index 7bc29a81..620c062e 100644
--- a/common/src/main/java/org/fiware/tmforum/common/repository/TmForumRepository.java
+++ b/common/src/main/java/org/fiware/tmforum/common/repository/TmForumRepository.java
@@ -104,9 +104,9 @@ public Mono> findEntities(Integer offset, Integer limit, Stri
* {@code typeToClass} instead of a single fixed class.
*/
public Mono> findEntitiesPolymorphic(Integer offset, Integer limit, String types,
- String query, String orderBy, Function> typeToClass) {
+ String query, String ids, String orderBy, Function> typeToClass) {
return entitiesApi.queryEntities(generalProperties.getTenant(),
- null,
+ ids,
null,
types,
null,
diff --git a/common/src/main/java/org/fiware/tmforum/common/rest/AbstractApiController.java b/common/src/main/java/org/fiware/tmforum/common/rest/AbstractApiController.java
index 9497c5a9..853320ee 100644
--- a/common/src/main/java/org/fiware/tmforum/common/rest/AbstractApiController.java
+++ b/common/src/main/java/org/fiware/tmforum/common/rest/AbstractApiController.java
@@ -182,6 +182,7 @@ protected Mono> listPolymorphic(Integer offset, Integer limit, Str
.findEntitiesPolymorphic(offset, limit,
Optional.ofNullable(queryParams).map(QueryParams::type).orElse(types),
Optional.ofNullable(queryParams).map(QueryParams::query).orElse(null),
+ Optional.ofNullable(queryParams).map(QueryParams::id).orElse(null),
orderBy,
typeToClass)
.doOnNext(pagedResult -> optionalHttpRequest.ifPresent(theRequest -> {
diff --git a/common/src/test/java/org/fiware/tmforum/common/repository/TmForumRepositoryTest.java b/common/src/test/java/org/fiware/tmforum/common/repository/TmForumRepositoryTest.java
index 69042c42..07a22431 100644
--- a/common/src/test/java/org/fiware/tmforum/common/repository/TmForumRepositoryTest.java
+++ b/common/src/test/java/org/fiware/tmforum/common/repository/TmForumRepositoryTest.java
@@ -1,12 +1,20 @@
package org.fiware.tmforum.common.repository;
import io.micronaut.http.HttpResponse;
+import org.fiware.ngsi.api.EntitiesApiClient;
+import org.fiware.ngsi.model.EntityListVO;
import org.fiware.tmforum.common.configuration.GeneralProperties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import reactor.core.publisher.Mono;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
class TmForumRepositoryTest {
@@ -19,6 +27,28 @@ public void setUp() {
repository = new TmForumRepository(properties, null, null, null, null, null);
}
+ @Test
+ public void findEntitiesPolymorphicForwardsTheIdFilterToTheBroker() {
+ // Regression test: findEntitiesPolymorphic used to hard-code the broker's native
+ // "id" query param to null, silently dropping any ?id= filter on polymorphic list
+ // endpoints (e.g. resourceSpecification, which spans several NGSI-LD types).
+ EntitiesApiClient entitiesApi = mock(EntitiesApiClient.class);
+ TmForumRepository repositoryWithClient = new TmForumRepository(properties, entitiesApi, null, null, null, null);
+ String requestedId = "urn:ngsi-ld:software-specification:0e2d5c4a-cf51-43cf-a510-dff06f62f4a3";
+
+ when(entitiesApi.queryEntities(any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(),
+ any(), any(), any(), any(), any(), any()))
+ .thenReturn(Mono.just(HttpResponse.ok(new EntityListVO())));
+
+ repositoryWithClient
+ .findEntitiesPolymorphic(0, 10, "software-specification,resource-specification", null, requestedId,
+ null, type -> Object.class)
+ .block();
+
+ verify(entitiesApi).queryEntities(eq(properties.getTenant()), eq(requestedId), any(), any(), any(), any(),
+ any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any());
+ }
+
@Test
public void extractsTheConfiguredHeader() {
properties.setCountHeader("NGSILD-Results-Count");
diff --git a/common/src/test/java/org/fiware/tmforum/common/rest/AbstractApiControllerTest.java b/common/src/test/java/org/fiware/tmforum/common/rest/AbstractApiControllerTest.java
new file mode 100644
index 00000000..94c21a4a
--- /dev/null
+++ b/common/src/test/java/org/fiware/tmforum/common/rest/AbstractApiControllerTest.java
@@ -0,0 +1,58 @@
+package org.fiware.tmforum.common.rest;
+
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.context.ServerRequestContext;
+import org.fiware.tmforum.common.configuration.GeneralProperties;
+import org.fiware.tmforum.common.querying.MyPojo;
+import org.fiware.tmforum.common.querying.QueryParser;
+import org.fiware.tmforum.common.repository.PagedResult;
+import org.fiware.tmforum.common.repository.TmForumRepository;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class AbstractApiControllerTest {
+
+ private static class TestController extends AbstractApiController {
+ TestController(QueryParser queryParser, TmForumRepository repository) {
+ super(queryParser, null, repository, null);
+ }
+ }
+
+ @AfterEach
+ public void clearRequestContext() {
+ ServerRequestContext.set(null);
+ }
+
+ @Test
+ public void listPolymorphicForwardsTheIdFilterToTheRepository() {
+ // Regression test: listPolymorphic used to only forward "type" and "query" from the
+ // parsed request to the repository, silently dropping any ?id= filter - even though it
+ // was correctly parsed into QueryParams.id(). The non-polymorphic list() already forwarded
+ // it; listPolymorphic must do the same.
+ GeneralProperties properties = new GeneralProperties();
+ QueryParser queryParser = new QueryParser(properties);
+ TmForumRepository repository = mock(TmForumRepository.class);
+ TestController controller = new TestController(queryParser, repository);
+
+ String requestedId = "urn:ngsi-ld:software-specification:0e2d5c4a-cf51-43cf-a510-dff06f62f4a3";
+ ServerRequestContext.set(
+ HttpRequest.GET("/resourceSpecification?id=" + requestedId + "&fields=lifecycleStatus"));
+
+ when(repository.findEntitiesPolymorphic(any(), any(), any(), any(), any(), any(), any()))
+ .thenReturn(Mono.just(new PagedResult<>(List.of(), 0, 10, null)));
+
+ controller.listPolymorphic(0, 10, "software-specification,resource-specification", MyPojo.class,
+ type -> MyPojo.class).block();
+
+ verify(repository).findEntitiesPolymorphic(any(), any(), any(), any(), eq(requestedId), any(), any());
+ }
+}