title: one-to-many mapping problem with ModelMapper
body: <p>I just want to map a simple object including a one-to-many relation, however, it always returns this error.</p>
  
  <pre><code>1) Error mapping com.example.ProductDTO to com.example.Product
  1 error] with root cause
  java.lang.StackOverflowError: null
  </code></pre>
  
  <p>I simplified my classes and run again and again, but cannot find a solution. Below files for spring boot (repository, service, controller, entities, and DTOs).</p>
  
  <p>When I first send POST request to create the product with features (son at the bottom of the message), it creates entities and persist into db. When I send same json to update (PUT), it returns StackOverflow error.</p>
  
  <p>Is there a way to map Product class with ProductFeatures to related entity?</p>
  
  <p>Product.class</p>
  
  <pre><code>package com.example;
  import com.fasterxml.jackson.annotation.JsonManagedReference;
  import java.io.Serializable;
  import java.util.HashSet;
  import java.util.Set;
  import java.util.UUID;
  import javax.persistence.CascadeType;
  import javax.persistence.Column;
  import javax.persistence.Entity;
  import javax.persistence.FetchType;
  import javax.persistence.Id;
  import javax.persistence.OneToMany;
  import javax.persistence.Table;
  import javax.persistence.Version;
  import lombok.Getter;
  import lombok.Setter;
  
  @Getter
  @Setter
  @Entity
  @Table(name = "product")
  public class Product implements Serializable {
  
      @Id
      @Column(name = "id", columnDefinition = "BINARY(16)")
      private UUID id;
  
      @Version
      private Long version;
  
      @Column(length = 64, nullable = false)
      private String name;
  
      @Column(length = 128)
      private String description;
  
      @OneToMany(mappedBy = "product", fetch = FetchType.EAGER, orphanRemoval = true, cascade = CascadeType.PERSIST)
      @JsonManagedReference("product_features")
      private Set&lt;ProductFeature&gt; features = new HashSet&lt;&gt;();
  
      public Product() {
          this.id = UUID.randomUUID();
      }
  
      @Override
      public String toString() {
          return id.toString();
      }
  
      @Override
      public int hashCode() {
          return id.hashCode();
      }
  
      @Override
      public boolean equals(Object obj) {
          if (this == obj) {
              return true;
          }
          if (obj == null) {
              return false;
          }
          if (!(obj instanceof Product)) {
              return false;
          }
  
          Product other = (Product) obj;
  
          return getId().equals(other.getId());
      }
  
      public UUID getId() {
          return id;
      }
  
      public void setId(UUID id) {
          this.id = id;
      }
  }
  </code></pre>
  
  <p>ProductFeature.class</p>
  
  <pre><code>package com.example;
  
  import com.fasterxml.jackson.annotation.JsonBackReference;
  import java.io.Serializable;
  import java.util.UUID;
  import javax.persistence.Column;
  import javax.persistence.Entity;
  import javax.persistence.FetchType;
  import javax.persistence.Id;
  import javax.persistence.JoinColumn;
  import javax.persistence.ManyToOne;
  import javax.persistence.Table;
  import javax.persistence.Version;
  import lombok.Getter;
  import lombok.Setter;
  
  @Getter
  @Setter
  @Entity
  @Table(name = "productfeatures")
  public class ProductFeature implements Serializable {
  
      @Id
      @Column(name = "id", columnDefinition = "BINARY(16)")
      private UUID id;
  
      @Version
      private Long version;
  
      @Column
      private int type;
  
      @Column
      private int intValue;
  
      @ManyToOne(fetch = FetchType.LAZY)
      @JoinColumn(name = "product", nullable = false)
      @JsonBackReference("product_features")
      private Product product;
  
      public ProductFeature() {
          this.id = UUID.randomUUID();
      }
  
      @Override
      public String toString() {
          return id.toString();
      }
  
      @Override
      public int hashCode() {
          return id.hashCode();
      }
  
      @Override
      public boolean equals(Object obj) {
          if (this == obj) {
              return true;
          }
          if (obj == null) {
              return false;
          }
          if (!(obj instanceof ProductFeature)) {
              return false;
          }
  
          ProductFeature other = (ProductFeature) obj;
  
          return getId().equals(other.getId());
      }
  
      public UUID getId() {
          return id;
      }
  
      public void setId(UUID id) {
          this.id = id;
      }
  }
  </code></pre>
  
  <p>ProductDTO.class</p>
  
  <pre><code>package com.example;
  
  import com.fasterxml.jackson.annotation.JsonManagedReference;
  import java.io.Serializable;
  import java.util.HashSet;
  import java.util.Set;
  import java.util.UUID;
  import lombok.Getter;
  import lombok.Setter;
  
  @Getter
  @Setter
  public class ProductDTO implements Serializable {
  
      private UUID id;
      private String name;
      private String description;
  
      @JsonManagedReference("product_features")
      private Set&lt;ProductFeatureDTO&gt; features = new HashSet&lt;&gt;();
  
      public ProductDTO() {
          this.id = UUID.randomUUID();
      }
  
      @Override
      public String toString() {
          return id.toString();
      }
  
      @Override
      public int hashCode() {
          return id.hashCode();
      }
  
      @Override
      public boolean equals(Object obj) {
          if (this == obj) {
              return true;
          }
          if (obj == null) {
              return false;
          }
          if (!(obj instanceof ProductDTO)) {
              return false;
          }
  
          ProductDTO other = (ProductDTO) obj;
  
          return getId().equals(other.getId());
      }
  
      public UUID getId() {
          return id;
      }
  
      public void setId(UUID id) {
          this.id = id;
      }
  }
  </code></pre>
  
  <p>ProductFeatureDTO.class</p>
  
  <pre><code>package com.example;
  
  import com.fasterxml.jackson.annotation.JsonBackReference;
  import java.io.Serializable;
  import java.util.UUID;
  import lombok.Getter;
  import lombok.Setter;
  
  @Getter
  @Setter
  public class ProductFeatureDTO implements Serializable {
  
      private UUID id;
      private int type;
      private int intValue;
  
      @JsonBackReference("product_features")
      private ProductDTO product;
  
      public ProductFeatureDTO() {
          this.id = UUID.randomUUID();
      }
  
      @Override
      public String toString() {
          return id.toString();
      }
  
      @Override
      public int hashCode() {
          return id.hashCode();
      }
  
      @Override
      public boolean equals(Object obj) {
          if (this == obj) {
              return true;
          }
          if (obj == null) {
              return false;
          }
          if (!(obj instanceof ProductFeatureDTO)) {
              return false;
          }
  
          ProductFeatureDTO other = (ProductFeatureDTO) obj;
  
          return getId().equals(other.getId());
      }
  
      public UUID getId() {
          return id;
      }
  
      public void setId(UUID id) {
          this.id = id;
      }
  }
  </code></pre>
  
  <p>ProductRepository.class</p>
  
  <pre><code>package com.example;
  
  import java.util.UUID;
  import org.springframework.data.jpa.repository.JpaRepository;
  import org.springframework.stereotype.Repository;
  
  @Repository
  public interface ProductRepository extends JpaRepository&lt;Product, UUID&gt; {
  
  }
  </code></pre>
  
  <p>ProductRestController.class</p>
  
  <pre><code>package com.example;
  
  import java.security.Principal;
  import org.springframework.web.bind.annotation.RestController;
  import java.util.List;
  import java.util.UUID;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.http.ResponseEntity;
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.PathVariable;
  import org.springframework.web.bind.annotation.RequestBody;
  import org.springframework.web.bind.annotation.PostMapping;
  import org.springframework.web.bind.annotation.PutMapping;
  
  @RestController
  public class ProductRestController {
  
      @Autowired
      private ProductService productService;
  
      @GetMapping("/products")
      public List&lt;ProductDTO&gt; getProducts(Principal principal) {
          return productService.get();
      }
  
      @GetMapping("/products/{id}")
      public ProductDTO getProduct(@PathVariable UUID id) {
          return productService.get(id);
      }
  
      @PostMapping("/products")
      public ResponseEntity&lt;?&gt; create(@RequestBody ProductDTO input) {         
          return productService.create(input);
      }
  
      @PutMapping("/products/{id}")
      public ResponseEntity&lt;?&gt; update(@PathVariable UUID id, @RequestBody ProductDTO input) {
          return productService.update(id, input);
      }
  }
  </code></pre>
  
  <p>ProductService.class</p>
  
  <pre><code>package com.example;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.UUID;
  import org.modelmapper.ModelMapper;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.http.HttpStatus;
  import org.springframework.http.ResponseEntity;
  import org.springframework.stereotype.Service;
  
  @Service
  public class ProductService {
  
      @Autowired
      private ProductRepository productRepository;
  
      @Autowired
      private ModelMapper modelMapper;
  
      public List&lt;ProductDTO&gt; get() {
  
          List&lt;Product&gt; products = productRepository.findAll();
  
          List&lt;ProductDTO&gt; productDTOs = new ArrayList&lt;&gt;();
          for (Product product : products) {
              ProductDTO productDTO = modelMapper.map(product, ProductDTO.class);
              productDTOs.add(productDTO);
          }
  
          return productDTOs;
      }
  
      public ProductDTO get(UUID id) {
          Product product = productRepository.findById(id).get();
  
          ProductDTO productDTO = modelMapper.map(product, ProductDTO.class);
  
          return productDTO;
      }
  
      public ResponseEntity&lt;?&gt; create(ProductDTO productDTO) {
          Product product = modelMapper.map(productDTO, Product.class);
  
          Product p = productRepository.save(product);
  
          return new ResponseEntity&lt;&gt;(modelMapper.map(p, ProductDTO.class), HttpStatus.OK);
      }
  
      public ResponseEntity&lt;?&gt; update(UUID id, ProductDTO productDTO) {
          Product foundproduct = productRepository.getOne(id);
  
          modelMapper.map(productDTO, foundproduct);
  
          Product p = productRepository.save(foundproduct);
  
          return new ResponseEntity&lt;&gt;(modelMapper.map(p, ProductDTO.class), HttpStatus.OK);
      }
  }
  </code></pre>
  
  <p>JSON</p>
  
  <pre><code>{
    "id" : "6d1ed14a-d464-415a-9181-a3396ee9cd3e",
    "name" : "Test Product 11",
    "features" : [ {
      "id" : "5103e648-180a-4fb8-bc98-98efc5edf1c1",
      "type" : 13,
      "intValue" : 1
    }, {
      "id" : "e43fdb3e-ce80-4b7b-98db-00117cabf7e2",
      "type" : 11,
      "intValue" : 1
    }, {
      "id" : "4798849a-d849-4987-bfcc-da92adf9f813",
      "type" : 12,
      "intValue" : 1
    }, {
      "id" : "abc6883e-cbd9-4557-ad66-5b4ca6ef4084",
      "type" : 10,
      "intValue" : 1
    }, {
      "id" : "bb594179-80f2-4051-989e-280406a42775",
      "type" : 14,
      "intValue" : 1
    } ]
  }
  </code></pre>