Check out the full series of Questions Management tutorial series here.
In the previous tutorial, we prepared all the necessary configurations to build API to find question by id in the Composite Question Service: an object containing all the information of a CompositeQuestion question including Question, Category and Option; a CoreCategoryService interface with an implementation of CoreCategoryServiceImpl that deals with Core Category Service; a CoreQuestionService interface with a CoreQuestionServiceImpl implementation that handles for the Core Question Service; a CoreOptionService interface with the implementation is CoreOptionServiceImpl that handles for the Core Option Service; a CompositeQuestionService interface that handles Core Services; a CompositeQuestionController defines APIs for Composite Question Service that start with “/question” and the Core Services information are configured in the application.properties file. Now, we are going to build this API!
In order to build API to find question by id, I first define a new method in CoreQuestionService that takes care of finding the question by id from the Core Question Service as follows:
1 |
Mono<Question> findQuestionById(String id); |
with implementation of this method in the CoreQuestionServiceImpl class is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 |
@Override public Mono<Question> findQuestionById(String id) { WebClient client = WebClient.builder() .baseUrl(getServiceUrl()) .build(); WebClient.ResponseSpec responseSpec = client.get() .uri("/question/" + id) .retrieve(); return responseSpec.bodyToMono(Question.class); } |
As you can see, the method above calls to the API finding the question by the id of the Core Question Service.
Next I’ll also define a new method in the CompositeQuestionService that combines the information from the Core Category Service and the Core Option Service to find question by id after receiving the result from the Core Question Service.
1 |
Mono<CompositeQuestion> findQuestionById(String id); |
The implementation of this method in the CompositeQuestionServiceImpl class similar to the findAllQuestions() method as follows:
1 2 3 4 5 6 7 8 9 10 11 |
@Override public Mono<CompositeQuestion> findQuestionById(String id) { Mono<Question> questionsFromCoreQuestionService = coreQuestionService.findQuestionById(id); return questionsFromCoreQuestionService.flatMap(question -> coreCategoryService.findById(question.getCategoryId()) .flatMap(category -> coreOptionService.getOptions(question.getId()) .collectList() .map(options -> new CompositeQuestion(question.getId(), question.getDescription(), category, options))) ).subscribeOn(Schedulers.elastic()); } |
The last thing we need to do is to add a new method to the CompositeQuestionController class to expose a GET “/{id}” request
1 2 3 4 |
@GetMapping("/{id}") public Mono<ResponseEntity<CompositeQuestion>> findQuestionById(@PathVariable(value = "id") String id) { } |
This method calls to the findQuestionById() method of the CompositeQuestionService:
1 2 3 4 5 6 |
@GetMapping("/{id}") public Mono<ResponseEntity<CompositeQuestion>> findQuestionById(@PathVariable(value = "id") String id) { return compositeQuestionService.findQuestionById(id) .map(compositeQuestion -> ResponseEntity.ok(compositeQuestion)) .defaultIfEmpty(ResponseEntity.notFound().build()); } |
As you can see in the case where no question is found with the id passed by the user, this API will return a 404 Not Found error.
OK, here we have completed the construction of API search question by id for Composite Question Service. Let’s test it.