I have a basic Spring boot app and I am trying to map a list of entities to list of DTOs using Mapstruct (version 1.3.0.Final).
Source:
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable;
import java.sql.Timestamp;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@Table(name = "source")
@Entity(name = "Source")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Source implements Serializable {
private static final long serialVersionUID = 964150155782995534L;
@Id
@JsonIgnore
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SourceSeq")
@SequenceGenerator(sequenceName = "source_id_seq", allocationSize = 1, name = "SourceSeq")
private long id;
@NotNull
@Size(min = 36, max = 36)
@Column(name = "uuid", nullable = false, length = 36)
private String uuid;
@Column(name = "user_id")
private Long userId;
@Column(name = "username")
private String username;
@Column(name = "user_org_id")
private Long userOrgId;
@Column(name = "user_org_name")
private String userOrgName;
@Column(name = "account_number")
private Integer accountNumber;
@Column(name = "account_name")
private String accountName;
@Column(name = "billing_delay")
private Integer billingDelay;
@Column(name = "default_billing_delay")
private Integer defaultBillingDelay;
@Column(name = "billing_enabled")
private Boolean billingEnabled = true;
@JsonIgnore
@CreationTimestamp
@Column(name = "created_date")
private Timestamp createdDate;
@JsonIgnore
@UpdateTimestamp
@Column(name = "updated_date")
private Timestamp updatedDate;
}
Target:
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Target implements Serializable {
private static final long serialVersionUID = 8939532280496355293L;
@ApiModelProperty(hidden = true)
private String uuid;
@ApiModelProperty(value = "user ID", example = "123456", dataType = "int64", position = 1)
private Long userId;
@ApiModelProperty(value = "username", example = "myUser", position = 2)
private String username;
@ApiModelProperty(hidden = true)
private String firstName;
@ApiModelProperty(hidden = true)
private String lastName;
@ApiModelProperty(value = "user organization ID", example = "71836", dataType = "int64", position = 3)
private Long userOrgId;
@ApiModelProperty(value = "user organization name", example = "Org Inc", position = 4)
private String userOrgName;
@ApiModelProperty(value = "account number", example = "987654", position = 5)
private Integer accountNumber;
@ApiModelProperty(value = "account name", example = "My Mapping Acc", position = 6)
private String accountName;
@ApiModelProperty(value = "billing delay (in days)", example = "60", position = 7)
private Integer billingDelay;
@ApiModelProperty(value = "default billing delay (in days)", example = "30", position = 8)
private Integer defaultBillingDelay;
@ApiModelProperty(value = "is billing enabled?", example = "true", position = 9)
private Boolean billingEnabled = true;
@ApiModelProperty(hidden = true)
private Date createdDate;
}
Mapper:
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper
public interface MyMapper {
MyMapper MAPPER = Mappers.getMapper(MyMapper.class);
// Target toTarget(Source source);
// I have tried using this as well but my target mapped list only contains billingEnabled = true for every object in the response list. MapperImpl class also included below. Without toTarget method get a compilation error (also included below)
// Response:
/*[
{
"billingEnabled": true
},
{
"billingEnabled": true
},
{
"billingEnabled": true
}
]*/
List<Target> toTargets(List<Source> sources);
}
MapperImpl:
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2019-09-16T00:06:14-0700",
comments = "version: 1.3.0.Final, compiler: javac, environment: Java 1.8.0_202 (Oracle Corporation)"
)
public class MyMapperImpl implements MyMapper {
@Override
public Target toTarget(Source source) {
if ( source == null ) {
return null;
}
Target target = new Target();
return target;
}
@Override
public List<Target> toTargets(List<Source> sources) {
if ( sources == null ) {
return null;
}
List<Target> list = new ArrayList<Target>( sources.size() );
for ( Source source : sources ) {
list.add( toTarget( source ) );
}
return list;
}
}
Error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.5.1:compile (default-compile) on project my-project: Compilation failure
[ERROR] /Users/user8812/workspace/my-project-/src/main/java/MyMapper.java:[17,23] Can't map Collection element "Source source" to "Target target". Consider to declare/implement a mapping method: "Target map(Source value)".
I'm looking to have Target list with the same field names mapped without another individual toTarget method as that has worked for me in another project with an older Mapstruct version.