2
votes

I am currently trying to perform an Entity to DTO mapping using ModelMapper's map method. On the deepest property mapping, the mapping result is null but it should be an object.

These are my mapping source Entities(Omitting Loombok Getters and Setters for brevety):

public class Client implements Serializable
{       
  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  public Long id;

  @NotEmpty
  public String name;

  @NotEmpty
  public String surname;

  @NotEmpty
  @Email
  public String email;

  @Column(name="creation_date", updatable=false)
  @Temporal(TemporalType.DATE)
  @DateTimeFormat(pattern="yyyy-MM-dd")
  public Date creationDate;

  public String photo;

  @OneToMany(mappedBy="client", fetch=FetchType.LAZY, cascade=CascadeType.ALL, orphanRemoval=true)
  public List<Invoice> invoices;
}

public class Invoice implements Serializable
{    
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  public Long id;

  @NotEmpty
  public String description;

  public String comment;

  @Temporal(TemporalType.DATE)
  @Column(name = "creation_date", updatable = false)
  @DateTimeFormat(pattern = "yyyy-MM-dd")
  public Date creationDate;

  @ManyToOne(fetch = FetchType.LAZY)
  public Client client;

  @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  @JoinColumn(name = "invoice_id")
  public List<InvoiceItem> items;
}

public class InvoiceItem implements Serializable
{   
  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  public Long id;

  public Integer amount;

  @ManyToOne(fetch=FetchType.EAGER) 
  @JoinColumn(name="product_id")
  public Product product;
}

public class Product implements Serializable
{   
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public Long id;

    public String name;
    public Double prize;

    @Temporal(TemporalType.DATE)
    @Column(name="creation_date", updatable=false)
    @DateTimeFormat(pattern="yyyy-MM-dd")
    public Date creationDate;
}

And these are my target DTOs(Omitting Loombok Getters and Setters for brevety):

public class ClientDTO implements Serializable
{
    @JsonIgnore
    public Long id;

    public String name;

    public String surname;

    public String email;

    @JsonIgnore
    public Date creationDate;

    public String photo;
}

public class ClientWithInvoicesDTO extends ClientDTO implements Serializable
{
    @JsonManagedReference
    public List<InvoiceDTO> invoices;
}

public class InvoiceDTO implements Serializable
{
    @JsonIgnore
    public Long id;

    public String description;

    public String comment;

    public Date creationDate;

    @JsonBackReference
    public ClientDTO client;

    public List<InvoiceItemDTO> items;
}

public class InvoiceItemDTO implements Serializable
{
    @JsonIgnore
    public Long id;

    public Integer amount;

    public ProductDTO productDTO;   
}

public class ProductDTO implements Serializable
{
    @JsonIgnore
    public Long id;

    public String name;

    public Double prize;

    @JsonIgnore
    public Date creationDate;
}

And on my Controller class method I am doing mapping like this:

@RequestMapping(value = "/{id}/with-invoices", method = RequestMethod.GET)
public ResponseEntity findOneWithInvoices(@PathVariable Long id)
{
    Client wantedClient = this.clientService.findOneWithInvoices(id);

    ClientWithInvoicesDTO wantedClientWithInvoicesDto = this.modelMapper.map(wantedClient, ClientWithInvoicesDTO.class);

    return new ResponseEntity<>(wantedClientWithInvoicesDto, HttpStatus.OK);
}

My clientService is correctly returning the data but "product" property is null on JSON response and it shouldn't be:

{
    "name": "cupiditate",
    "surname": "veritatis",
    "email": "[email protected]",
    "photo": "ec0327a5-3de8-328c-a812-9000d6d5507d",
    "invoices": [
        {
            "description": "Distinctio autem id vel necessitatibus unde omnis rerum. Minus maxime quos doloribus. Voluptatem amet praesentium sit magni quia molestiae. Officia aspernatur numquam ut perspiciatis a.",
            "comment": "Odio enim libero tempore molestiae.",
            "creationDate": "2013-02-16",
            "items": [
                {
                    "amount": 6,
                    "productDTO": null
                },
...

Can anyone help me with this?

2
There is no product on InvoiceDto. Either create an explicit mapping for this (not sure if ModelMapper can handle that or how to do that) or rename the productDTO field to product. - M. Deinum
Oh, that was the problem !! "productDTO" field should be "product". Thanks so much - Gonzalo Zas Regueira

2 Answers

0
votes

Shouldn't you put @Entity before your class? Like that:

@Entity
public class MyClass {
...
}
0
votes

As M. Deinum says on comment below, on InvoiceItemDTO product property should be named as "product" instead of "productDTO". Now it works fine