Check out the full series of Questions Management tutorial here.
Unlike the Core Category Service, the API Category Service only receives a request and then calls the Core Category Service to perform this request. Therefore, in order to build API adding new category in API Category Service, there are a few things we have to do first.
The first thing we need to do is add a new Category object to contain the category information.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.huongdanjava.categoryservice.dto; import lombok.Data; @Data public class Category { private String id; private String code; private String name; private String description; } |
Because the API Category Service will call to the Core Category Service, so I will configure the Core Category Service information in the application.properties file as follows:
1 |
corecategoryservice.url=http://localhost:8082 |
To handle the call to the Core Category Service, I will create an interface called CoreCategoryService:
1 2 3 4 5 6 7 |
package com.huongdanjava.categoryservice.service; public interface CoreCategoryService { String getServiceUrl(); } |
with the implementation is CoreCategoryServiceImpl:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.huongdanjava.categoryservice.service.impl; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import com.huongdanjava.categoryservice.service.CoreCategoryService; @Service public class CoreCategoryServiceImpl implements CoreCategoryService { @Value("${corecategoryservice.url}") private String coreCategoryServiceUrl; @Override public String getServiceUrl() { return coreCategoryServiceUrl; } } |
As you can see, in the CoreCategoryServiceImpl class, I’ve injected information about the base URL of the Core Category Service.
I will run this service using port 8282 so I will also add the server.port property in the application.properties file as follows:
1 |
server.port=8282 |
OK, everything is ready, now I will go to the main part of this tutorial.
Similar to the Core Category Service, I will create a controller named CategoryController with the following content:
1 2 3 4 5 6 7 8 9 10 |
package com.huongdanjava.categoryservice; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/category") public class CategoryController { } |
With this declaration, I also expose APIs for the API Category Service with the request URL that starts with “/category”.
Next, we will inject CoreCategoryService into CategoryController to use:
1 2 |
@Autowired private CoreCategoryService coreCategoryService; |
To build API adding new category, I will add a new method in the CoreCategoryService class named:
1 |
Mono<Category> save(Category category); |
with implementation as follows:
1 2 3 4 5 6 7 8 9 10 11 12 |
@Override public Mono<Category> save(Category category) { WebClient webClient = WebClient.builder() .baseUrl(getServiceUrl()) .build(); return webClient.post() .uri("/category/add") .body(BodyInserters.fromObject(category)) .retrieve() .bodyToMono(Category.class); } |
As you can see, here I have used the WebClient object to connect to the Core Category Service and call the API adding new category of this service with the URI “/category/add”.
Then I will add a new method in CategoryController to expose a POST request “/add” with the data in the body as a Category object:
1 2 3 4 |
@PostMapping("/add") public Mono<Category> createCategory(@RequestBody Category category) { } |
Our task is to simply call the save() method of CoreCategoryService:
1 2 3 4 |
@PostMapping("/add") public Mono<Category> createCategory(@RequestBody Category category) { return coreCategoryService.save(category); } |
At this point we have completed building a new API for adding new category for the API Category Service, let’s test it.
The last thing we need to do is add a new Unit Test to the code that we just added.
I will create a class named CategoryControllerTest located in the src/test/java folder, com.huongdanjava.categoryservice package to test the CategoryController class.
1 2 3 4 5 |
package com.huongdanjava.categoryservice; public class CategoryControllerTest { } |
Next, I will mock the CoreCategoryService object and inject it into CategoryController as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.huongdanjava.categoryservice; import org.mockito.InjectMocks; import org.mockito.Mock; import com.huongdanjava.categoryservice.service.CoreCategoryService; public class CategoryControllerTest { @Mock private CoreCategoryService coreCategoryService; @InjectMocks private CategoryController categoryController; } |
To use mock objects, we have to initialize them before running one test case, so we will add a method with the JUnit @Before annotation as follows:
1 2 3 4 |
@Before public void init() { MockitoAnnotations.initMocks(this); } |
The code to test the createCategory() method is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@Test public void testCreateCategory() { // Create object need to create Category category = new Category(); category.setCode("ABC"); category.setName("ZXC"); // The result should be the same with additional id field Category result = category; result.setId("123"); // Mock save() method of CategoryRepository when(coreCategoryService.save(category)).thenReturn(Mono.just(result)); // Call method Mono<Category> createdCategoryAsMono = categoryController.createCategory(category); Category createdCategory = createdCategoryAsMono.block(); // Assertions assertEquals("ABC", createdCategory.getCode()); assertEquals("ZXC", createdCategory.getName()); assertEquals("123", createdCategory.getId()); } |
Run “Maven test” in STS or “mvn test” with Apache Maven, you will not see any errors.