Xem toàn bộ series bài viết hướng dẫn xây dựng ứng dụng Questions Management tại đây.
Khác với Core Category Service, API Category Service chỉ sẽ nhận request rồi gọi đến Core Category Service để service này thực hiện yêu cầu của người dùng. Do đó, để xây dựng API thêm mới category, có mấy việc sau chúng ta phải làm trước.
Việc đầu tiên, chúng ta cần làm là thêm mới một đối tượng Category để chứa thông tin của category.
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; } |
Vì API Category Service sẽ gọi đến Core Category Service nên mình sẽ cấu thông tin về Core Category Service trong tập tin application.properties như sau:
1 |
corecategoryservice.url=http://localhost:8082 |
Để handle việc gọi tới Core Category Service, mình sẽ tạo một interface tên là CoreCategoryService:
1 2 3 4 5 6 7 |
package com.huongdanjava.categoryservice.service; public interface CoreCategoryService { String getServiceUrl(); } |
với implementation là 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; } } |
Như các bạn thấy, trong class CoreCategoryServiceImpl, mình đã inject sẵn thông tin về base URL của Core Category Service.
Mình sẽ chạy service này sử dụng port 8282 nên mình cũng sẽ thêm property server.port trong tập tin application.properties như sau:
1 |
server.port=8282 |
OK, mọi thứ chuẩn bị đã xong, bây giờ mình sẽ đi vào phần chính của bài viết này các bạn nhé!
Tương tự như Core Category Service, mình sẽ tạo mới một controller tên là CategoryController với nội dung như sau:
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 { } |
Với khai báo trên, mình cũng đã expose các API cho phần API Category Service với request URL bắt đầu là “/category”.
Tiếp theo chúng ta sẽ inject CoreCategoryService vào CategoryController để sử dụng:
1 2 |
@Autowired private CoreCategoryService coreCategoryService; |
Để xây dựng API thêm mới category, mình sẽ thêm mới một method trong class CoreCategoryService tên là:
1 |
Mono<Category> save(Category category); |
với implementation như sau:
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); } |
Như các bạn thấy, ở đây mình đã sử dụng đối tượng WebClient để kết nối tới Core Category Service và gọi API thêm mới category của service này với URI “/category/add”.
Sau đó, mình sẽ thêm mới một method trong CategoryController để expose một POST request “/add” với data trong phần body là đối tượng Category:
1 2 3 4 |
@PostMapping("/add") public Mono<Category> createCategory(@RequestBody Category category) { } |
Nhiệm vụ của chúng ta chỉ là gọi tới phương thức save() của CoreCategoryService mà thôi:
1 2 3 4 |
@PostMapping("/add") public Mono<Category> createCategory(@RequestBody Category category) { return coreCategoryService.save(category); } |
Đến đây thì chúng ta đã hoàn thành việc xây dựng API thêm mới category cho API Category Service, hãy test thử xem sao nhé các bạn.
Phần cuối cùng mà chúng ta cần làm là thêm mới Unit Test cho code mà chúng ta vừa thêm vào các bạn nhé!
Mình sẽ tạo mới một class tên là CategoryControllerTest nằm trong thư mục src/test/java, package com.huongdanjava.categoryservice để test cho class CategoryController.
1 2 3 4 5 |
package com.huongdanjava.categoryservice; public class CategoryControllerTest { } |
Tiếp theo, mình sẽ mock đối tượng CoreCategoryService và inject nó vào CategoryController như sau:
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; } |
Để sử dụng các đối tượng mock, chúng ta phải khởi tạo chúng trước mỗi lần test một phương thức nên mình sẽ thêm một phương thức với annotation @Before của JUnit như sau:
1 2 3 4 |
@Before public void init() { MockitoAnnotations.initMocks(this); } |
Code để test phương thức createCategory() như sau:
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()); } |
Chạy “Maven test” trong STS hoặc “mvn test” với Apache Maven, các bạn sẽ không lỗi nào cả.