diff --git a/src/main/kotlin/org/springframework/hateoas/server/reactive/ReactiveRepresentationModelAssemblerBuildDsl.kt b/src/main/kotlin/org/springframework/hateoas/server/reactive/ReactiveRepresentationModelAssemblerBuildDsl.kt index 051ea829..11ed0806 100644 --- a/src/main/kotlin/org/springframework/hateoas/server/reactive/ReactiveRepresentationModelAssemblerBuildDsl.kt +++ b/src/main/kotlin/org/springframework/hateoas/server/reactive/ReactiveRepresentationModelAssemblerBuildDsl.kt @@ -20,8 +20,20 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.reactive.awaitFirst import kotlinx.coroutines.reactor.asFlux import org.springframework.hateoas.CollectionModel +import org.springframework.hateoas.EntityModel import org.springframework.hateoas.RepresentationModel import org.springframework.web.server.ServerWebExchange +import reactor.core.publisher.Mono + +/** + * Add support for Kotlin co-routines. + * + * @author Greg Turnquist + * @since 1.1 + */ +suspend fun > ReactiveRepresentationModelAssembler.toModelAndAwait( + entity: T, + exchange: ServerWebExchange): D = toModel(entity, exchange).awaitFirst() /** * Add support for Kotlin co-routines. @@ -30,6 +42,19 @@ import org.springframework.web.server.ServerWebExchange * @author Greg Turnquist * @since 1.1 */ +@Deprecated("use toCollectionModelAndAwait(entites, exchange)", + replaceWith = ReplaceWith("toCollectionModelAndAwait(entities, exchange)")) suspend fun > ReactiveRepresentationModelAssembler.toCollectionModel( + entities: Flow, + exchange: ServerWebExchange): CollectionModel = toCollectionModelAndAwait(entities, exchange) + +/** + * Add support for Kotlin co-routines. + * + * @author Juergen Zimmerman + * @author Greg Turnquist + * @since 1.1 + */ +suspend fun > ReactiveRepresentationModelAssembler.toCollectionModelAndAwait( entities: Flow, exchange: ServerWebExchange): CollectionModel = toCollectionModel(entities.asFlux(), exchange).awaitFirst() diff --git a/src/main/kotlin/org/springframework/hateoas/server/reactive/SimpleReactiveRepresentationModelAssemblerBuildDsl.kt b/src/main/kotlin/org/springframework/hateoas/server/reactive/SimpleReactiveRepresentationModelAssemblerBuildDsl.kt index d35721e0..5676899b 100644 --- a/src/main/kotlin/org/springframework/hateoas/server/reactive/SimpleReactiveRepresentationModelAssemblerBuildDsl.kt +++ b/src/main/kotlin/org/springframework/hateoas/server/reactive/SimpleReactiveRepresentationModelAssemblerBuildDsl.kt @@ -23,6 +23,30 @@ import org.springframework.hateoas.CollectionModel import org.springframework.hateoas.EntityModel import org.springframework.web.server.ServerWebExchange +/** + * Add support for Kotlin co-routines. + * + * @author Greg Turnquist + * @since 1.1 + */ +suspend fun SimpleReactiveRepresentationModelAssembler.toModelAndAwait( + entity: T, + exchange: ServerWebExchange): EntityModel = toModel(entity, exchange).awaitFirst() + +/** + * Add support for Kotlin co-routines. + * + * @author Juergen Zimmerman + * @author Greg Turnquist + * @since 1.1 + * + */ +@Deprecated("use toCollectionModelAndAwait(entites, exchange)", + replaceWith = ReplaceWith("toCollectionModelAndAwait(entities, exchange)")) +suspend fun SimpleReactiveRepresentationModelAssembler.toCollectionModel( + entities: Flow, + exchange: ServerWebExchange): CollectionModel> = toCollectionModelAndAwait(entities, exchange) + /** * Add support for Kotlin co-routines. * @@ -30,6 +54,7 @@ import org.springframework.web.server.ServerWebExchange * @author Greg Turnquist * @since 1.1 */ -suspend fun SimpleReactiveRepresentationModelAssembler.toCollectionModel( +suspend fun SimpleReactiveRepresentationModelAssembler.toCollectionModelAndAwait( entities: Flow, exchange: ServerWebExchange): CollectionModel> = toCollectionModel(entities.asFlux(), exchange).awaitFirst() + diff --git a/src/test/kotlin/org/springframework/hateoas/server/reactive/ReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt b/src/test/kotlin/org/springframework/hateoas/server/reactive/ReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt index 36409c8a..200d66a2 100644 --- a/src/test/kotlin/org/springframework/hateoas/server/reactive/ReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt +++ b/src/test/kotlin/org/springframework/hateoas/server/reactive/ReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt @@ -31,23 +31,38 @@ import reactor.core.publisher.Mono * @author Greg Turnquist * @since 1.1 */ + class ReactiveRepresentationModelAssemblerBuilderDslUnitTest : TestUtils() { - private val EMPLOYEES_RELATION = LinkRelation.of("employees") + val EMPLOYEES_RELATION = LinkRelation.of("employees") private val employees = flow { emit(Employee("Frodo")) emit(Employee("Bilbo")) } - @Test // #1213 - fun `Kotlin Flows should render as CollectionModels`() { + @Test // #1275 + fun `Kotlin co-routine should render as a RepresentationModel`() { val testResourceAssembler = TestResourceAssembler() val exchange = mockk() runBlocking { - val collectionModel = testResourceAssembler.toCollectionModel(employees, exchange) + val model = testResourceAssembler.toModelAndAwait(Employee("Frodo"), exchange) + + assertThat(model.content.name).isEqualTo("Frodo") + assertThat(model.links).containsExactlyInAnyOrder(Link.of("/employees", EMPLOYEES_RELATION)) + } + } + + @Test // #1213 + fun `Kotlin co-routine should render as CollectionModels`() { + + val testResourceAssembler = TestResourceAssembler() + val exchange = mockk() + + runBlocking { + val collectionModel = testResourceAssembler.toCollectionModelAndAwait(employees, exchange) assertThat(collectionModel.content.flatMap { entityModel -> entityModel.links }) .containsExactlyInAnyOrder(Link.of("/employees", EMPLOYEES_RELATION), Link.of("/employees", EMPLOYEES_RELATION)) @@ -55,6 +70,7 @@ class ReactiveRepresentationModelAssemblerBuilderDslUnitTest : TestUtils() { } class TestResourceAssembler : ReactiveRepresentationModelAssembler> { + override fun toModel(entity: Employee, exchange: ServerWebExchange): Mono> { return Mono.just(EntityModel.of(entity, Link.of("/employees", LinkRelation.of("employees")))) } diff --git a/src/test/kotlin/org/springframework/hateoas/server/reactive/SimpleReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt b/src/test/kotlin/org/springframework/hateoas/server/reactive/SimpleReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt index aa647dbf..00a45ae7 100644 --- a/src/test/kotlin/org/springframework/hateoas/server/reactive/SimpleReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt +++ b/src/test/kotlin/org/springframework/hateoas/server/reactive/SimpleReactiveRepresentationModelAssemblerBuilderDslUnitTest.kt @@ -34,21 +34,43 @@ class SimpleReactiveRexpresentationModelAssemblerBuilderDslUnitTest : TestUtils( emit(Employee("Bilbo")) } - @Test // #1213 - fun `Kotlin Flows should render as CollectionModels`() { + @Test // #1275 + fun `Kotlin co-routine should render as a RepresentationModel`() { val testResourceAssembler = SimpleTestResourceAssembler() val exchange = mockk() runBlocking { - val collectionModel = testResourceAssembler.toCollectionModel(employees, exchange) + val model = testResourceAssembler.toModelAndAwait(Employee("Frodo"), exchange) + + assertThat(model.content.name).isEqualTo("Frodo") + assertThat(model.links).containsExactlyInAnyOrder(Link.of("/employees", LinkRelation.of("employees"))) + } + } + + @Test // #1213 + fun `Kotlin co-routine should render as CollectionModels`() { + + val testResourceAssembler = SimpleTestResourceAssembler() + val exchange = mockk() + + runBlocking { + val collectionModel = testResourceAssembler.toCollectionModelAndAwait(employees, exchange) assertThat(collectionModel.links).containsExactly(Link.of("/employees")) } } class SimpleTestResourceAssembler : SimpleReactiveRepresentationModelAssembler { + + override fun addLinks(resource: EntityModel, exchange: ServerWebExchange): EntityModel { + + resource.add(Link.of("/employees", LinkRelation.of("employees"))) + return resource + } + override fun addLinks(resources: CollectionModel>, exchange: ServerWebExchange): CollectionModel> { + resources.add(Link.of("/employees")) return resources }