I work on API Rest project with Spring. I have a service "CreateMateriel" which takes as parameter data JSON :
JSON of Materiel Object
{
  "agence": 1, 
  "code": "001",
  "type": "MyType"
}
"Materiel" has a relation Many to One with "Agence". I put a @JsonIdentityInfo tag to use Agence's Id and not Agence's Object (After seeing this topic)
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "idAgence")
@JsonIdentityReference(alwaysAsId = true)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "agence")
private Agence agence;
But when I send JSON on POST /materiels I have this exception:
2017-05-16 18:00:53.021  WARN 8080 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Unresolved forward references for: 
 at [Source: java.io.PushbackInputStream@767dfd7a; line: 5, column: 1]Object id [1] (for fr.app.domain.Agence) at [Source: java.io.PushbackInputStream@767dfd7a; line: 2, column: 14].; nested exception is com.fasterxml.jackson.databind.deser.UnresolvedForwardReference: Unresolved forward references for: 
 at [Source: java.io.PushbackInputStream@767dfd7a; line: 5, column: 1]Object id [1] (for fr.app.domain.Agence) at [Source: java.io.PushbackInputStream@767dfd7a; line: 2, column: 14].
After many research I have seen the use of ObjectIdResolver in JsonIdentityInfo ... But I think this is not the best solution. This is why I ask for your help in detecting the source of the problem. Thank's
MaterielController.java
package fr.app.controllers;
import fr.app.domain.Materiel;
import fr.app.services.MaterielService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Collection;
@RestController @RequestMapping(value = "/materiels")
public class MaterielController {
    @Resource
    private MaterielService materielService;
    @RequestMapping(method = RequestMethod.POST)
    public Materiel createMateriel(@RequestBody Materiel materiel) {
        return this.materielService.createMateriel(materiel);
    }
    @RequestMapping(method = RequestMethod.GET)
    public Collection<Materiel> getAllMateriels() {
        return this.materielService.getAllMateriels();
    }
    @RequestMapping(value = "/{code}", method = RequestMethod.GET)
    public Materiel getMaterielByCode(@PathVariable(value = "code") String code) {
        //find materiel by code
        return this.materielService.getMaterielByCode(code);
    }
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public void deleteMateriel(@PathVariable(value = "id") Long id) {
        this.materielService.deleteMateriel(id);
    }
    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public Materiel updateMateriel(@PathVariable(value = "id") Long id, @RequestBody
            Materiel materiel) {
            materiel.setIdMateriel(id);
        return this.materielService.updateMateriel(materiel);
    }
}
Materiel.java
package fr.app.domain;
import com.fasterxml.jackson.annotation.*;
import javax.persistence.*;
@Entity
public class Materiel {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long idMateriel;
    @Column(name = "type_materiel", nullable = false)
    private String type;
    @Column(name = "code_materiel", unique = true, nullable = false)
    private String code;
    @JsonIdentityInfo(
            generator = ObjectIdGenerators.PropertyGenerator.class,
            property = "idAgence")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "agence")
    private Agence agence;
    public Materiel() {    }
    public Materiel(String type, String code, String dateScan) {
        this.type = type;
        this.code = code;
        this.dateScan = dateScan;
    }
    public Long getIdMateriel() {
        return idMateriel;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public Agence getAgence() {
        return agence;
    }
    public void setAgence(Agence agence) {
        if(this.agence != null)
            this.agence.deleteMateriel(this);
        this.agence = agence;
        this.agence.addMateriel(this);
    }
}
MaterielService.java
package fr.app.services;
import fr.app.domain.Materiel;
import fr.app.repositories.MaterielRepository;
import org.apache.commons.collections.IteratorUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collection;
@Service(value = "materielService")
public class MaterielServiceImpl implements MaterielService {
    @Resource
    private MaterielRepository materielRepository;
    ...
    @Override
    public Materiel createMateriel(Materiel materiel) {
        return this.materielRepository.save(materiel);
    }
   ...
}
Agence.java
package fr.app.domain;
import com.fasterxml.jackson.annotation.*;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@Entity
public class Agence {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long idAgence;
    @Column(name = "nom",unique = true, nullable = false)
    private String nom;
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "agence")
    private Set<Materiel> materiels = new HashSet<Materiel>();
    public Agence() { }
    public Agence(String nom) {
        this.nom = nom;
    }
    public Long getIdAgence() {
        return idAgence;
    }
    public String getNom() {
        return nom;
    }
    public void setNom(String nom) {
        this.nom = nom;
    }
    public Set<Materiel> getMateriels() {
        return materiels;
    }
    public void setMateriels(Set<Materiel> materiels) {
        this.materiels = materiels;
    }
    public void addMateriel(Materiel materiel) {
        this.materiels.add(materiel);
    }
    public void deleteMateriel(Materiel materiel) {
        this.materiels.remove(materiel);
    }
}
pom.xml
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.0</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.2.9.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>5.2.9.Final</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.6.1</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.2.2</version>
        <scope>compile</scope>
    </dependency>
    <!-- Needed for JSON View -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.6</version>
    </dependency>
</dependencies>
 
     
     
     
     
    