Abdullah Imran
Abdullah Imran

Reputation: 399

How to merge two different Mono to produce final response in java reactive

In getProductById method I am trying to construct Mono<OrderResponse> from Mono<Book> and Mono<Container> like shown below. The issue is response structure what this method is returning different from what I should get.

 public Mono<OrderResponse> getProductById(Integer id) {

        Mono<Book> monoBook=Mono.just(id).
            flatMap(ops.service(BookingDomainService.class)::getProductById);

        Mono<Container> monoCon=Mono.just(id).
            flatMap(ops.service(BookingDomainService.class)::getContainerById);

        OrderResponse or=new OrderResponse(monoBook,monoCon);
        return Mono.just(or);
    }

Structure of BOOK, Container and Response class are below.

My Book Class :


@Data
@AllArgsConstructor
@Builder
@NoArgsConstructor
public class Book implements Serializable {
    @Id
    private Integer id;

    @Column
    private String name;

    @Column
    private Long price;
}

Container Class:


public class Container {
  private String containerName;
  private String description;

  public String getContainerName() {
    return containerName;
  }

  public void setContainerName(String containerName) {
    this.containerName = containerName;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }
}

My Response class:


public class OrderResponse {
  private Mono<Book> orderMono;
  private Mono<Container> orderContainerMono;

  public Mono<Book> getOrderMono() {
    return orderMono;
  }

  public void setOrderMono(Mono<Book> orderMono) {
    this.orderMono = orderMono;
  }

  public Mono<Container> getOrderContainerMono() {
    return orderContainerMono;
  }

  public void setOrderContainerMono(
      Mono<Container> orderContainerMono) {
    this.orderContainerMono = orderContainerMono;
  }

  public OrderResponse(Mono<Book> orderMono, Mono<Container> orderContainerMono) {
    this.orderMono = orderMono;
    this.orderContainerMono = orderContainerMono;
  }
}

Final response that is being formed from method getProductById(Integer id) is

{
    "orderMono": {
        "scanAvailable": true
    },
    "orderContainerMono": {
        "scanAvailable": true
    }
}

but I need final response as:

I need final response as below json. How to achieve it.

Response:
{
  "Book": {
    "id": 12,
    "name": "pn",
    "price": 128
  },
  "Container": {
    "containerName": " Cname",
    "description": "diesc"
  }
}

Upvotes: 1

Views: 2905

Answers (1)

Alex R
Alex R

Reputation: 3311

You can use Mono.zip to aggreate the results of multiple Monos into a single one that will be fulfilled when all of the given Monos have produced an item.

public final class OrderResponse {
    private final Book book;
    private final Container container;

    public OrderResponse(Book book, Container container) {
        this.book = book;
        this.container = container;
    }

    // ...
}

public Mono<OrderResponse> getProductById(Integer id) {
    // replace these lines with your actual calls
    Mono<Book> bookMono = Mono.just(new Book(1, "Book 1", 1L));
    Mono<Container> containerMono = Mono.just(new Container("A", "B"));

    return Mono.zip(bookMono, containerMono)
            .map(tuple -> new OrderResponse(tuple.getT1(), tuple.getT2()));
}

If you want to return a OrderResponse object directly instead of it being wrapped in a Mono, you can check out the Mono#block method.

Upvotes: 5

Related Questions