How to correctly wrap a Flux inside a Mono object

6.5k views Asked by At

I have a web-service which returns student and enrolled class details.

{
  "name": "student-name",
  "classes": [
    {
      "className": "reactor-101",
      "day": "Tuesday"
    },
    {
      "className": "reactor-102",
      "day": "Friday"
    }
  ]
}

The DTO for this class is as below:

public class Student {
        private String name;
        private Flux<StudentClass> classes;
        @Data
        @AllArgsConstructor
        @JsonInclude(JsonInclude.Include.NON_DEFAULT)
        public static class StudentClass {
            private String className;
            private String day;
        }
    }

The main REST controller logic to fetch the student is as follows:

Flux<StudentClass> studentClassFlux = studentClassRepository.getStudentClass(studentName);

return Mono.just(new Student(studentName, studentClassFlux));

The problem with this is, I get the following output after making the REST call:

{
  "name": "student-name",
  "classes": {
    "prefetch": 32,
    "scanAvailable": true
  }
}

I can achieve the desired output by blocking on the flux request to get completed and then convert the output to list.

List<StudentClass> studentClassList = studentClassRepository.getStudentClass(studentName)..toStream().collect(Collectors.toList());
return Mono.just(new Student(studentName, studentClassList)); // Change the Student#classes from flux to list

I am new to reactive-programming. What is the correct way of using the Flux & Mono here to get the desired output?

2

There are 2 answers

1
Brian Clozel On BEST ANSWER

Reactive types aren't meant to be serialized when wrapped in each other. In that particular case, you probably want your Student object to contain a List<StudentClass>. You can achieve that like this:

public Mono<Student> findStudent(String studentName) {

    return studentClassRepository
             .getStudentClass(studentName)
             .collectList()
             .map(studentClasses -> new Student(studentName, studentClasses));
}
0
user1373147 On

I think, in the case that you really need a Flux in your result, you would want to break down the API so that you have separate methods to retrieve the entities. One for student properties, and another for their classes. The student GET method could be a Mono, while the classes would return a Flux.