Please look at the below code from controller(Added comments) which uses RestTemplate:
@GetMapping("/{courseid}")
public Course getCourseDetails(@PathVariable Long courseid) {
// Get Course info (ID, Name, Description) from pre-populated Array List
CourseInfo courseInfo = getCourseInfo(courseid);
// Get Price info of a course from another microservice using RESTTemplate
Price price = restTemplate.getForObject("http://localhost:8002/price/"+courseid, Price.class);
// Get enrollment info of a course from another microservice using RESTTemplate
Enrollment enrollment = restTemplate.getForObject("http://localhost:8003/enrollment/"+courseid, Enrollment.class);
//Consolidate everything in to Course object and send it as response
return new Course(courseInfo.getCourseID(), courseInfo.getCourseName(), courseInfo.getCourseDesc(), price.getDiscountedPrice(),
enrollment.getEnrollmentOpen());
}
Now I am trying to achieve the same using Reactive programming. I now use WebClient and Mono from Web-Flux. But, I am so confused as to how to combine the results? Take a look at the below code (Just using Mono Everywhere. Rest of the code remained same)
@GetMapping("/{courseid}")
public Mono<Course> getCourseDetails(@PathVariable Long courseid) {
// Get Course info (ID, Name, Description) from pre-populated Array List
CourseInfo courseInfo = getCourseInfo(courseid);
// Get Price info of a course from another microservice using RESTTemplate
Mono<Price> price = webClient.get().uri("http://localhost:8002/price/{courseid}/",courseid).retrieve().bodyToMono(Price.class);
// Get enrollment info of a course from another microservice using RESTTemplate
Mono<Enrollment> inventory = webClient.get().uri("http://localhost:8003/enrollment/{courseid}/",courseid).retrieve().bodyToMono(Enrollment.class);
//Question : How do we Consolidate everything and form a Mono<Course> object and send it as response?
}
Question 1 : How do we Consolidate everything and form a Mono object and send it as response?
Question 2 : Does the statement "CourseInfo courseInfo = getCourseInfo(courseid);" cause blocking operation?
Thanks!
Answering to:
Question 1 : How do we Consolidate everything and form a Mono object and send it as response?
Mono.zip(..) is what you need to combine the two results. This diagram is from the doc :
Note that, zip
will result in an empty Mono if one of A or 1 is empty! Use switchIfEmpty
/defaultIfEmpty
to protect against that case.
Thus the code looks like:
@GetMapping("/{courseid}")
public Mono<Course> getCourseDetails(@PathVariable Long courseid) {
CourseInfo courseInfo = getCourseInfo(courseid);
Mono<Price> priceMono = webClient.get().uri("http://localhost:8002/price/{courseid}/",courseid).retrieve().bodyToMono(Price.class);
Mono<Enrollment> enrollmentMono = webClient.get().uri("http://localhost:8003/enrollment/{courseid}/",courseid).retrieve().bodyToMono(Enrollment.class);
return Mono.zip(priceMono, enrollmentMono).map(t -> new Course(courseInfo.getCourseID(), courseInfo.getCourseName(), courseInfo.getCourseDesc(), t.getT1().getDiscountedPrice(),
t.getT2().getEnrollmentOpen()));
}
Now answering to:
Question 2 : Does the statement "CourseInfo courseInfo = getCourseInfo(courseid);" cause blocking operation?
Since you mentioned that Get Course info (ID, Name, Description) from pre-populated Array List
, if it is just an in-memory Array containing the course information, then it's not blocking.
But (as @mslowiak also mentioned), if getCourseInfo
contains logic which involves querying a database, ensure that you are not using a blocking JDBC driver. If so, then there is no point of using Webflux and Reactor. Use Spring R2DBC if that is the case.