0
votes

My REST controller method should return Mono which must be built of 2 parallel requests to another web services and processing their response where one request return Mono and another request return Flux

How to combine responses of Mono with Flux and process them?

Model:

@Document
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClassModel {

    @Id
    private String id;
    private String roomNr;
    private String className;
    private String teacherId;
    private List<String> studentIds;

    public void addStudentId(String studentId) {
        studentIds.add(studentId);
    }

}

Controller:

public Mono<ClassModel> addRandomClassFull() {
    return Mono.zip(
        //request teacher microservice and return Mono - single teacher
        reactiveNetClient.addRandomTeacher(),
        //request students microservice and return Flux - list of students
        reactiveNetClient.addRandomStudents(10),
        (teacher, students) -> {
            ClassModel classModel = new ClassModel();
            classModel.setRoomNr("24B");
            classModel.setClassName(faker.educator().course());
            classModel.setTeacherId(teacher.getId());
            students.forEach(student -> classModel.addStudentId(student.getId());
            return classModel;
        }).flatMap(classRepository::save);
}

Obviously, the controller is wrong as:
1) Mono.zip() takes 2 or more Mono's, where I have Mono and Flux - How to combine them?
2) Also not sure if:
students.forEach(student -> classModel.addStudentId(student.getId());
is right aproach?

Any suggestions, please?

1

1 Answers

1
votes
  1. You can change your method addRandomStudents() to return Mono<List<Student>>
  2. You can use collectList() on Flux<Student>, it will return then Mono<List<Student>> and then in addStudents() will convert Student object to id.

    public Mono<ClassModel> addRandomClassFull() {
        return Mono.zip(
            reactiveNetClient.addRandomTeacher(),
            reactiveNetClient.addRandomStudents(10).collectList(),
            (teacher, students) -> {
                 ClassModel classModel = new ClassModel();
                 classModel.setRoomNr("24B");
                 classModel.setClassName(faker.educator().course());
                 classModel.setTeacherId(teacher.getId());
                 classModel.addStudents(students);
            return classModel;
        }).flatMap(classRepository::save);
    }