Not sure if it is an anti pattern, but if you want an immutable DTO and have lots of properties then setting via constructor seems unreasonable and ugly. Could use a nested Builder class to set the properties and expose the builder through a public method, but seems like over-engineering unless there is a compelling reason to not have setter methods on the DTO.
Thus, unless there is a business requirement for the class to be immutable, just use setters on the DTO.
otherwise, take a look at this over-engineered solution with a trivial domain class.
The domain model class...
public class User {
private int id;
private String username;
private String password;
// getters and setters
The DTO with a nested Builder...
public class UserDto {
private int id;
private String username;
public int getId() {
return id;
}
public String getUsername() {
return username;
}
public static Builder fromBuilder() {
return new Builder();
}
static class Builder {
private final UserDto user;
private Builder() {
user = new UserDto();
}
public Builder withId(int id) {
user.id = id;
return this;
}
public Builder withUsername(String username) {
user.username = username;
return this;
}
public UserDto build() {
return user;
}
}
}
The mapper...
public class UserMapper {
public UserDto toUserDto(User user) {
return UserDto.fromBuilder()
.withId(user.getId())
.withUsername(user.getUsername())
.build();
}
}
A simple test...
class UserDtoTest {
UserMapper mapper = new UserMapper();
@Test
void shouldBuild() {
User user = new User();
user.setId(1234);
user.setUsername("user1234");
user.setPassword("super_secret_password");
UserDto dto = mapper.toUserDto(user);
assertEquals(user.getId(), dto.getId());
assertEquals(user.getUsername(), dto.getUsername());
}
}