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 CategoryMapper interface using MapStruct for efficient mapping
  • Added post count calculation filtering only published posts
  • Completed CategoryController implementation with proper DTO conversion
  • Verified endpoint functionality through manual testing
© 2026 Devtiro Ltd. All rights reserved