Project Reactor expand method
One of my colleagues at work recently introduced me to the expand operator of the Project Reactor types and in this post I want to cover a few ways in which I have used it.
Unrolling a Paginated Result
Consider a Spring Data based repository on a model called City:
1 2 3 4 5 | import org.springframework.data.jpa.repository.JpaRepository; import samples.geo.domain.City; public interface CityRepo extends JpaRepository<City, Long> { } |
This repository provides a way to retrieve the paginated result, along the following lines:
1 | cityRepo.findAll(PageRequest.of( 0 , 5 )) |
Now, if I were to unroll multiple pages into a result, the way to do it would be the following kind of a loop:
1 2 3 4 5 6 | var pageable: Pageable = PageRequest.of( 0 , 5 ) do { var page: Page<City> = cityRepo.findAll(pageable) page.content.forEach { city -> LOGGER.info( "City $city" ) } pageable = page.nextPageable() } while (page.hasNext()) |
An equivalent unroll of a paginated result can be done using the Reactor expand operator the following way:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | val result: Flux<City> = Mono .fromSupplier { cityRepo.findAll(PageRequest.of( 0 , 5 )) } .expand { page -> if (page.hasNext()) Mono.fromSupplier { cityRepo.findAll(page.nextPageable()) } else Mono.empty() } .flatMap { page -> Flux.fromIterable(page.content) } result.subscribe( { page -> LOGGER.info( "City ${page}" ) }, { t -> t.printStackTrace() } ) |
Here the first page of results expands to the second page, the second page to the third page and so on until there are no pages to retrieve.
Traversing a Tree
Consider a node in a tree structure represented by the following model:
1 2 3 4 | data class Node( val id: String, val nodeRefs: List<String>, ) |
A sample data which looks like this:
can be traversed using a call which looks like this:
1 2 3 4 5 6 | val rootMono: Mono<Node> = nodeService.getNode( "1" ) val expanded: Flux<Node> = rootMono.expand { node -> Flux.fromIterable(node.childRefs) .flatMap { nodeRef -> nodeService.getNode(nodeRef) } } expanded.subscribe { node -> println(node) } |
This is a breadth-first expansion, the output looks like this:
1 2 3 4 5 6 7 | Node- 1 Node- 1 - 1 Node- 1 - 2 Node- 1 - 1 - 1 Node- 1 - 1 - 2 Node- 1 - 2 - 1 Node- 1 - 2 - 2 |
An expandDeep variation would traverse it depth-first
Published on Java Code Geeks with permission by Biju Kunjummen, partner at our JCG program. See the original article here: Project Reactor expand method Opinions expressed by Java Code Geeks contributors are their own. |