diff --git a/data-model/src/main/java/io/micronaut/data/model/CursoredPage.java b/data-model/src/main/java/io/micronaut/data/model/CursoredPage.java index 950377b6fa..eecab0aa96 100644 --- a/data-model/src/main/java/io/micronaut/data/model/CursoredPage.java +++ b/data-model/src/main/java/io/micronaut/data/model/CursoredPage.java @@ -52,7 +52,7 @@ @DefaultImplementation(DefaultCursoredPage.class) public interface CursoredPage extends Page { - CursoredPage EMPTY = new DefaultCursoredPage<>(Collections.emptyList(), Pageable.unpaged(), Collections.emptyList(), null); + CursoredPage EMPTY = new DefaultCursoredPage<>(Collections.emptyList(), Pageable.unpaged(), Collections.emptyList(), -1L); /** * @return Whether this {@link CursoredPage} contains the total count of the records @@ -125,6 +125,9 @@ default CursoredPageable previousPageable() { */ @Override default @NonNull CursoredPage map(Function function) { + if (this == EMPTY) { + return (CursoredPage) EMPTY; + } List content = getContent().stream().map(function).collect(Collectors.toList()); return new DefaultCursoredPage<>(content, getPageable(), getCursors(), hasTotalSize() ? getTotalSize() : null); } diff --git a/data-model/src/main/java/io/micronaut/data/model/Page.java b/data-model/src/main/java/io/micronaut/data/model/Page.java index 12efe23840..844b5d2823 100644 --- a/data-model/src/main/java/io/micronaut/data/model/Page.java +++ b/data-model/src/main/java/io/micronaut/data/model/Page.java @@ -96,6 +96,9 @@ default boolean hasNext() { */ @Override default @NonNull Page map(Function function) { + if (this == EMPTY) { + return (Page) EMPTY; + } List content = getContent().stream().map(function).toList(); return new DefaultPage<>(content, getPageable(), hasTotalSize() ? getTotalSize() : null); } diff --git a/data-model/src/test/groovy/io/micronaut/data/model/PageSpec.groovy b/data-model/src/test/groovy/io/micronaut/data/model/PageSpec.groovy index c068745423..cc2d1c4aa3 100644 --- a/data-model/src/test/groovy/io/micronaut/data/model/PageSpec.groovy +++ b/data-model/src/test/groovy/io/micronaut/data/model/PageSpec.groovy @@ -199,6 +199,24 @@ class PageSpec extends Specification { !mappedCursoredPage.hasTotalSize() } + void "empty page can be mapped "() { + when: + Page page = Page.empty() + def copy = page.map { it -> it } + copy.getTotalSize() + + then: + notThrown(Throwable) + + when: + CursoredPage cursoredPage = CursoredPage.empty() + def newCopy = cursoredPage.map {it -> it } + newCopy.getTotalSize() + + then: + notThrown(Throwable) + } + @EqualsAndHashCode @ToString @Serdeable diff --git a/src/main/docs/guide/azureCosmos/azureCosmosCriteriaSpecifications.adoc b/src/main/docs/guide/azureCosmos/azureCosmosCriteriaSpecifications.adoc index 9af8a1be9c..f67b2d5bb3 100644 --- a/src/main/docs/guide/azureCosmos/azureCosmosCriteriaSpecifications.adoc +++ b/src/main/docs/guide/azureCosmos/azureCosmosCriteriaSpecifications.adoc @@ -4,7 +4,7 @@ dependency:jakarta.persistence:jakarta.persistence-api[] To implement queries that cannot be defined at the compile-time Micronaut Data introduces api:data.repository.JpaSpecificationExecutor[] repository interface that can be used to extend your repository interface: -snippet::example.PersonRepository[project-base="doc-examples/mongo-example",source="main" tags="repository",indent="0"] +snippet::example.PersonRepository[project-base="doc-examples/azure-cosmos-example",source="main" tags="repository",indent="0"] Each method expects a "specification" which is a functional interface with a set of Criteria API objects intended to build a query programmatically.