Search code examples
javamapstruct

@Mapping annotation is not mapping correctly to convert Entity object to DTO object


I am using @Mapping to map my entity class to DTO class.All values are being mapped perfectly except one- hostPlayerId is coming null.

I am hitting my API below which is returning Lobby object and I am using MapStruct to map the Entity to the DTO. Its mapping every field except hostPlayerId field.

@GetMapping("/lobby/{id}")
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public LobbyGetDTO getLobbyInfo(@RequestHeader("X-Auth-Token") String token, @PathVariable("id") long id) {
    Lobby lobby = lobbyService.getLobby(id);
    log.info("here here "+lobby.toString());
    LobbyGetDTO lobbyInfoDTO = DTOMapper.INSTANCE.convertEntityToLobbyGetDTO(lobby);
    log.info(lobbyInfoDTO.toString());
    return lobbyInfoDTO;
}

The logger after hitting the API -

2020-04-18 00:00:01.738  INFO 18486 --- [nio-8080-exec-6] c.u.i.s.s.controller.LobbyController     : here here Lobby{id=2, name='Test Lobby', hostPlayerId=1, playerIds=[], chatId=null, gameId=null, status=0}

2020-04-18 00:00:01.740  INFO 18486 --- [nio-8080-exec-6] c.u.i.s.s.controller.LobbyController     : LobbyGetDTO{id=2, name='Test Lobby', hostPlayerId=null, playerIds=[], gameId=null}

Map Interface-

 @Mapper
public interface DTOMapper {

    DTOMapper INSTANCE = Mappers.getMapper(DTOMapper.class);

    @Mapping(source = "id", target = "id")
    @Mapping(source = "name", target = "name")
    @Mapping(source = "gameId", target = "gameId")
    @Mapping(source = "hostPlayerId", target = "hostPlayerId")
    @Mapping(source = "playerIds", target = "playerIds")
    LobbyGetDTO convertEntityToLobbyGetDTO(Lobby lobby);
}

mapping implementation method created during build phase-

 @Override
public LobbyGetDTO convertEntityToLobbyGetDTO(Lobby lobby) {
    if ( lobby == null ) {
        return null;
    }

    LobbyGetDTO lobbyGetDTO = new LobbyGetDTO();

    lobbyGetDTO.setGameId( lobby.getGameId() );
    lobbyGetDTO.setName( lobby.getName() );
    lobbyGetDTO.setId( lobby.getId() );
    List<Long> list = lobby.getPlayerIds();
    if ( list != null ) {
        lobbyGetDTO.setPlayerIds( new ArrayList<Long>( list ) );
    }
    lobbyGetDTO.sethostPlayerId( lobby.gethostPlayerId() );

    return lobbyGetDTO;
}

My DTO class

public class LobbyGetDTO {

    private Long id;
    private String name;
    private Long hostPlayerId;
    private List<Long> playerIds;
    private Long gameId;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long gethostPlayerId() {
        return hostPlayerId;
    }

    public void sethostPlayerId(Long hostPlayerIdPlayerId) {
        this.hostPlayerId = hostPlayerId;
    }

    public List<Long> getPlayerIds() {
        return playerIds;
    }

    public void setPlayerIds(List<Long> playerIds) {
        this.playerIds = playerIds;
    }

    public Long getGameId() {
        return gameId;
    }

    public void setGameId(Long gameId) {
        this.gameId = gameId;
    }
}

My Entity class

@Entity
@Table(name = "LOBBY")
public class Lobby implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private Long hostPlayerId;
}

I am unable to understand what am I missing here.


Solution

  • Maybe, getter and setter in the DTO need to be named as getHostPlayerId() / setHostPlayerId() so that the mapper could detect them.

    Also, you do not assign any value in the setter because of typo in the argument:

        public void sethostPlayerId(Long hostPlayerIdPlayerId) {
            this.hostPlayerId = hostPlayerId;
        }
    

    should be:

        public void setHostPlayerId(Long hostPlayerId) {
            this.hostPlayerId = hostPlayerId;
        }