List Categories Endpoint Part 2
In our previous lesson, we created the initial structure for listing categories, but we still need to convert our domain entities to DTOs.
We'll implement a MapStruct mapper to handle this conversion efficiently, completing our category listing endpoint.
This will enable us to properly format our category data for API responses while maintaining clean separation between our domain and API layers.
Creating the Mappers Package
MapStruct mappers require their own dedicated package for organization and clarity.
Let's create a new package at src/main/java/com/devtiro/blog/mappers.
In this package, we'll house all our mapper interfaces that handle entity-to-DTO conversions.
Implementing the Category Mapper
The CategoryMapper interface defines how to convert between Category entities and CategoryDto objects:
package com.devtiro.blog.mappers;
import com.devtiro.blog.domain.PostStatus;
import com.devtiro.blog.domain.dtos.CategoryDto;
import com.devtiro.blog.domain.entities.Category;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.ReportingPolicy;
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CategoryMapper {
@Mapping(target = "postCount", source = "posts", qualifiedByName = "calculatePostCount")
CategoryDto toDto(Category category);
@Named("calculatePostCount")
default long calculatePostCount(java.util.Set<com.devtiro.blog.domain.entities.Post> posts) {
if (posts == null) {
return 0;
}
return posts.stream()
.filter(post -> PostStatus.PUBLISHED.equals(post.getStatus()))
.count();
}
}Completing the Category Controller
Now we can use our mapper to convert entities to DTOs in the controller:
@RestController
@RequestMapping("/api/v1/categories")
@RequiredArgsConstructor
public class CategoryController {
private final CategoryService categoryService;
private final CategoryMapper categoryMapper;
@GetMapping
public ResponseEntity<List<CategoryDto>> listCategories() {
List<Category> categories = categoryService.listCategories();
return ResponseEntity.ok(
categories.stream().map(categoryMapper::toDto).toList()
);
}
}Testing the Endpoint
The categories endpoint is now ready for testing.
Navigate to http://localhost:8080/api/v1/categories in your browser or use a tool like Postman.
You should see a JSON response containing a list of categories with their IDs, names, and post counts.
Summary
- Created dedicated mappers package for entity-to-DTO conversion logic
- Implemented
CategoryMapperinterface using MapStruct for efficient mapping - Added post count calculation filtering only published posts
- Completed
CategoryControllerimplementation with proper DTO conversion - Verified endpoint functionality through manual testing