Search code examples
jsonspring-data-jparepository-patterncrudresttemplate

How do I POST through RestTemplate a class with embedded members?


I have a class with a few members, and the associated setters and getters:

public class Tester implements Serializable {
  @Column(name="ID", nullable=false, unique=true)   
  @Id   
  @GeneratedValue(generator="LOCATION_FACILITYTYPE_ID_GENERATOR")   
  @org.hibernate.annotations.GenericGenerator(name="LOCATION_FACILITYTYPE_ID_GENERATOR", strategy="native") 
  private int ID;

  @Column(name="Value", nullable=false, unique=true, length=4)  
  private String value;

  @Column(name="Name", nullable=false, unique=true, length=8)   
  private String name;

  @ManyToOne(targetEntity=location.FacilityType.class, fetch=FetchType.LAZY)    
  @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.LOCK})  
  @JoinColumns({ @JoinColumn(name="FacilityTypeID", referencedColumnName="ID", nullable=false) })   
  private location.FacilityType facility;

In a JUnit, I am trying to test creating a Tester element:

    Tester trythis = new Tester();
    trythis.setName("Herewe");
    trythis.setValue("wow1");
    Tester jnode = restTemplate.postForObject(TestBase.URL + "tester/", trythis, Tester.class);

This works as expected. However, if I use code like this to include an embedded member:

    FacilityType ft = new FacilityType();       
    ft.setValue("AL");
    ft.setName("2adamlec");
    Tester trythis = new Tester();
    trythis.setName("Herewe");
    trythis.setValue("wow1");
    trythis.setFacility(ft);
    Tester jnode = restTemplate.postForObject(TestBase.URL + "tester/", trythis, Tester.class);

where the embedded member with value=AL does not yet appear in the database, I still get a new row created in the Tester table ... but the value and name columns in Tester are filled with the values (AL and 2adamlec) defined for FacilityType.

Note that we are using the JPARepository framework for FacilityType and Tester. The CRUD functions are thus handled 'under the covers', and I can't debug the POST processing. I wonder if this is associated with the fact that a GET for Tester data will only return the primitive fields in the JSON reply, since there is no projection defined for FacilityType.

Am I doing something wrong to cause the FacilityType fields to be saved in lieu of the desired Tester fields in the Tester table?


Solution

  • The short answer: when creating the item, you have to provide the data in the same JSON format that the server expects it. If you have an embedded class, you have to create a class where the facility member is a String to house a URL, then set that member to the URL corresponding to the existing instance of the embedded class. On the receiving end, you also need a new class like this:

    public class FMT_Tester_RCV {
      public FMT_Tester_RCV() { }
    
      private String value;
      private String name;
      private Integer id;
      private Integer ormid;
      private JsonNode _links;
    

    where you can travel down the JsonNode to get the link to the embedded class instance.