We were given an assignment to recreate a simple version of the Twitter API in Spring using Mapstruct.
We are returning a List<UserDto>
that should return the field username
from the embedded object Credentials
.
We mapped this as follows:
@Mapper(componentModel = "spring", uses = {ProfileMapper.class, CredentialMapper.class}) public interface UserMapper { User dtoToEntity(CreateUserDto createUserDto); @Mapping(target = "username", source = "credentials.username") List<UserDto> entitiesToDtos(List<User> users); }
Our UserDto
is specified like this:
@NoArgsConstructor @Data public class UserDto { private ProfileDto profile; private Timestamp joined; private String username; }
Our User
entity has an embedded object named credentials
, where the username
and password
of the user are stored in String format (I know this is dumb, this is just an assignment).
@NoArgsConstructor @Entity @Data @Table(name="users") public class User { @Id @GeneratedValue private Long id; @CreationTimestamp private Timestamp joined; private boolean deleted; @Embedded private Credential credentials; @Embedded private Profile profile;
Long story short, when we GET all users, we should receive this (these are fake names and numbers):
{ "profile": { "firstName": "Chanda", "lastName": "Hackett", "email": "chandahackett@gmail.com", "phone": "313-574-1401" }, "joined": "2021-03-17T21:15:35.289+00:00", "username": "chandahackett" }
But instead, we receive a null
value for username:
{ "profile": { "firstName": "Chanda", "lastName": "Hackett", "email": "chandahackett@gmail.com", "phone": "313-574-1401" }, "joined": "2021-03-17T21:15:35.289+00:00", "username": null }
I know the value username in credentials exists, as it exists in the table it is stored:
And it is accessible because other methods that call user.getCredentials().getUsername()
return the right username.
I have tried pretty much everything. I have run mvn clean install
, renamed variables. I’m out of ideas. Any help would be appreciated.
Advertisement
Answer
The way you’re trying to use @Mapping
on a collection-mapping method isn’t supported at the moment. You need to declare an explicit mapping from User
to UserDto
, and apply the annotation on it instead:
@Mapper(componentModel = "spring", uses = {ProfileMapper.class, CredentialMapper.class}) public interface UserMapper { User dtoToEntity(CreateUserDto createUserDto); @Mapping(target = "username", source = "credentials.username") UserDto entityToDto(User user); List<UserDto> entitiesToDtos(List<User> users); }