Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

November Discount Launch 2022 – Top
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:


NPI – Lightrun – Spring (partner)

We rely on other people’s code in our own work. Every day. It might be the language you’re writing in, the framework you’re building on, or some esoteric piece of software that does one thing so well you never found the need to implement it yourself.

The problem is, of course, when things fall apart in production - debugging the implementation of a 3rd party library you have no intimate knowledge of is, to say the least, tricky. It’s difficult to understand what talks to what and, specifically, which part of the underlying library is at fault.

Lightrun is a new kind of debugger.

It's one geared specifically towards real-life production environments. Using Lightrun, you can drill down into running applications, including 3rd party dependencies, with real-time logs, snapshots, and metrics. No hotfixes, redeployments, or restarts required.

Learn more in this quick, 5-minute Lightrun tutorial:

>> The Essential List of Spring Boot Annotations and Their Use Cases

1. Overview

In this tutorial, we'll handle the conversions that need to happen between the internal entities of a Spring application and the external DTOs (Data Transfer Objects) that are published back to the client.

Further reading:

Spring's RequestBody and ResponseBody Annotations

Learn about the Spring @RequestBody and @ResponseBody annotations.

Quick Guide to MapStruct

A quick and practical guide to using MapStruct

2. Model Mapper

Let's start by introducing the main library that we're going to use to perform this entity-DTO conversion, ModelMapper.

We will need this dependency in the pom.xml:


To check if there's any newer version of this library, go here.

Then we'll define the ModelMapper bean in our Spring configuration:

public ModelMapper modelMapper() {
    return new ModelMapper();

3. The DTO

Next let's introduce the DTO side of this two-sided problem, Post DTO:

public class PostDto {
    private static final SimpleDateFormat dateFormat
      = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    private Long id;

    private String title;

    private String url;

    private String date;

    private UserDto user;

    public Date getSubmissionDateConverted(String timezone) throws ParseException {
        return dateFormat.parse(this.date);

    public void setSubmissionDate(Date date, String timezone) {
        this.date = dateFormat.format(date);

    // standard getters and setters

Note that the two custom date related methods handle the date conversion back and forth between the client and the server:

  • getSubmissionDateConverted() method converts date String into a Date in the server's timezone to use it in the persisting Post entity
  • setSubmissionDate() method is to set DTO's date to Post‘s Date in current user timezone

4. The Service Layer

Now let's look at a service level operation, which will obviously work with the Entity (not the DTO):

public List<Post> getPostsList(
  int page, int size, String sortDir, String sort) {
    PageRequest pageReq
     = PageRequest.of(page, size, Sort.Direction.fromString(sortDir), sort);
    Page<Post> posts = postRepository
      .findByUser(userService.getCurrentUser(), pageReq);
    return posts.getContent();

We're going to have a look at the layer above service next, the controller layer. This is where the conversion will actually happen.

5. The Controller Layer

Next let's examine a standard controller implementation, exposing the simple REST API for the Post resource.

We're going to show here a few simple CRUD operations: create, update, get one, and get all. Given that the operations are pretty straightforward, we are especially interested in the Entity-DTO conversion aspects:

class PostRestController {

    private IPostService postService;

    private IUserService userService;

    private ModelMapper modelMapper;

    public List<PostDto> getPosts(...) {
        List<Post> posts = postService.getPostsList(page, size, sortDir, sort);
        return posts.stream()

    public PostDto createPost(@RequestBody PostDto postDto) {
        Post post = convertToEntity(postDto);
        Post postCreated = postService.createPost(post));
        return convertToDto(postCreated);

    @GetMapping(value = "/{id}")
    public PostDto getPost(@PathVariable("id") Long id) {
        return convertToDto(postService.getPostById(id));

    @PutMapping(value = "/{id}")
    public void updatePost(@PathVariable("id") Long id, @RequestBody PostDto postDto) {
        if(!Objects.equals(id, postDto.getId())){
            throw new IllegalArgumentException("IDs don't match");
        Post post = convertToEntity(postDto);

Here is our conversion from Post entity to PostDto:

private PostDto convertToDto(Post post) {
    PostDto postDto = modelMapper.map(post, PostDto.class);
    return postDto;

Here is the conversion from DTO to an entity:

private Post convertToEntity(PostDto postDto) throws ParseException {
    Post post = modelMapper.map(postDto, Post.class);
    if (postDto.getId() != null) {
        Post oldPost = postService.getPostById(postDto.getId());
    return post;

So as we can see, with the help of the model mapper, the conversion logic is quick and simple. We're using the map API of the mapper, and getting the data converted without writing a single line of conversion logic.

6. Unit Testing

Finally, let's do a very simple test to make sure the conversions between the entity and the DTO work well:

public class PostDtoUnitTest {

    private ModelMapper modelMapper = new ModelMapper();

    public void whenConvertPostEntityToPostDto_thenCorrect() {
        Post post = new Post();

        PostDto postDto = modelMapper.map(post, PostDto.class);
        assertEquals(post.getId(), postDto.getId());
        assertEquals(post.getTitle(), postDto.getTitle());
        assertEquals(post.getUrl(), postDto.getUrl());

    public void whenConvertPostDtoToPostEntity_thenCorrect() {
        PostDto postDto = new PostDto();

        Post post = modelMapper.map(postDto, Post.class);
        assertEquals(postDto.getId(), post.getId());
        assertEquals(postDto.getTitle(), post.getTitle());
        assertEquals(postDto.getUrl(), post.getUrl());

7. Conclusion

In this article, we detailed simplifying the conversion from Entity to DTO, and from DTO to Entity in a Spring REST API, by using the model mapper library instead of writing these conversions by hand.

The full source code for the examples is available in the GitHub project.

November Discount Launch 2022 – Bottom
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:


REST footer banner
Comments are closed on this article!