Issue
I couldn't find the info I'm looking for hence posting here for suggestion and getting to know better approach.
I have an immutable DTO object like:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.LocalDate;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AccountCreateDto {
String name;
Long accountNo;
String email;
LocalDate dob;
String address;
Long phone;
Integer amount;
LocalDate accountOpeningDate;
Integer installmentAmount;
Integer totalAmount;
LocalDate installmentPaidDate;
@JsonCreator
public AccountCreateDto(
@JsonProperty("name") String name,
@JsonProperty("accountNo") Long accountNo,
@JsonProperty("email") String email,
@JsonProperty("dob") LocalDate dob,
@JsonProperty("address") String address,
@JsonProperty("phone") Long phone,
@JsonProperty("amount") Integer amount,
@JsonProperty("accountOpeningDate") LocalDate accountOpeningDate,
@JsonProperty("installmentAmount") Integer installmentAmount,
@JsonProperty("totalAmount") Integer totalAmount,
@JsonProperty("installmentPaidDate") LocalDate installmentPaidDate
) {
this.name = name;
this.accountNo = accountNo;
this.email = email;
this.dob = dob;
this.address = address;
this.phone = phone;
this.amount = amount;
this.accountOpeningDate = accountOpeningDate;
this.installmentAmount = installmentAmount;
this.totalAmount = totalAmount;
this.installmentPaidDate = installmentPaidDate;
}
// removing getters for brevity
}
Now I'm working on an integration test with testcontainer where I want the accountOpeningDate
and installmentPaidDate
to be dynamic value hence in order to set these values from Integration Tests, is it a good idea to add only 2 setters to this DTO which is only to be used for Integration Tests like below?
public void setAccountOpeningDate(LocalDate accountOpeningDate) {
this.accountOpeningDate = accountOpeningDate;
}
public void setInstallmentPaidDate(LocalDate installmentPaidDate) {
this.installmentPaidDate = installmentPaidDate;
}
Or is there a better approach than this? Looking for recommendations.
TA
Solution
It is not acceptable you will lose the immutability of the object. With immutable classes, we can’t modify the state but must create a new instance with the mutated state.
The builder pattern is very useful in this case.
Example:
AccountCreateDto existingImmutableDTO = new AccountCreateDto("name", 1L, "name@aaa", LocalDate.now(), "Address", null, null, null, null, null, null );
//change state of imuttable object, create new instance via builder
AccountCreateDto modifiedImmutableDTO = new AccountCreateDtoBuilder(existingImmutableDTO).setAccountOpeningDate(LocalDate.now()).setInstallmentPaidDate(LocalDate.now()).build();
public class AccountCreateDtoBuilder {
private String name;
private Long accountNo;
private String email;
private LocalDate dob;
private String address;
private Long phone;
private Integer amount;
private LocalDate accountOpeningDate;
private Integer installmentAmount;
private Integer totalAmount;
private LocalDate installmentPaidDate;
public AccountCreateDtoBuilder() {
}
public AccountCreateDtoBuilder(AccountCreateDto accountCreateDto) {
this.name = accountCreateDto.getName();
this.accountNo = accountCreateDto.getAccountNo();
this.email = accountCreateDto.getEmail();
this.dob = accountCreateDto.getDob();
this.address = accountCreateDto.getAddress();
this.phone = accountCreateDto.getPhone();
this.amount = accountCreateDto.getAmount();
this.accountOpeningDate = accountCreateDto.getAccountOpeningDate();
this.installmentAmount = accountCreateDto.getInstallmentAmount();
this.totalAmount = accountCreateDto.getTotalAmount();
this.installmentPaidDate = accountCreateDto.getInstallmentPaidDate();
}
public AccountCreateDto build() {
return new AccountCreateDto(name, accountNo, email, dob, address, phone, amount, accountOpeningDate, installmentAmount, totalAmount, installmentPaidDate);
}
public AccountCreateDtoBuilder setName(String name) {
this.name = name;
return this;
}
public AccountCreateDtoBuilder setAccountNo(Long accountNo) {
this.accountNo = accountNo;
return this;
}
public AccountCreateDtoBuilder setEmail(String email) {
this.email = email;
return this;
}
public AccountCreateDtoBuilder setDob(LocalDate dob) {
this.dob = dob;
return this;
}
public AccountCreateDtoBuilder setAddress(String address) {
this.address = address;
return this;
}
public AccountCreateDtoBuilder setPhone(Long phone) {
this.phone = phone;
return this;
}
public AccountCreateDtoBuilder setAmount(Integer amount) {
this.amount = amount;
return this;
}
public AccountCreateDtoBuilder setAccountOpeningDate(LocalDate accountOpeningDate) {
this.accountOpeningDate = accountOpeningDate;
return this;
}
public AccountCreateDtoBuilder setInstallmentAmount(Integer installmentAmount) {
this.installmentAmount = installmentAmount;
return this;
}
public AccountCreateDtoBuilder setTotalAmount(Integer totalAmount) {
this.totalAmount = totalAmount;
return this;
}
public AccountCreateDtoBuilder setInstallmentPaidDate(LocalDate installmentPaidDate) {
this.installmentPaidDate = installmentPaidDate;
return this;
}
}
Answered By - Eugene
Answer Checked By - Cary Denson (JavaFixing Admin)