I'm having trouble posting a JSON object from my UI to a Spring Boot controller.
Here is my controller, I have commented out the controller code and just return a new object. It seems that the JSON is not being parsed to the domain object correctly:
PersonnelController:
@Controller
@RequestMapping(value = "/Personnel")
public class PersonnelController {
@RequestMapping(value = "update", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Personnel updateJson(@RequestBody Personnel personnel) {
System.out.println("update personnel json : " + personnel.toString());
return new Personnel();
}
}
My controller is not a REST controller and I'm using content negotiation to be able to use Spring model and REST API together.
These are my classes :
User:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class User extends AbstractDomainClass {
@Column(unique = true)
private String username;
@Transient
private String password;
private String encryptedPassword;
private boolean enabled = true;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable
@JsonBackReference(value = "roles")
private List<Role> roles = new ArrayList<>();
}
Personnel:
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class Personnel extends User {
private String firstName;
private String lastName;
private long nationalId;
private long perssonnelId;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate birthDate;
@ManyToOne(fetch = FetchType.LAZY)
private Company company;
}
Company:
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Company extends AbstractDomainClass {
@Column(unique = true)
private String name;
private String description;
private String address;
private String adminName;
@OneToMany(fetch = FetchType.LAZY , cascade = CascadeType.PERSIST , orphanRemoval = true)
@JoinTable
@JsonBackReference
private List<Personnel> personnels = new ArrayList<>();
@OneToOne(fetch = FetchType.EAGER , cascade = CascadeType.ALL)
private User admin;
}
Role:
@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class Role extends AbstractDomainClass {
@Column(unique = true)
private String roleName;
@ManyToMany(fetch = FetchType.EAGER , mappedBy = "roles")
private List<User> users = new ArrayList<>();
@ManyToMany
@Fetch(FetchMode.SELECT)
private List<Permission> permissions = new ArrayList<>();
}
(I have omitted getters and setters.)
This is the JSON I'm posting to the controller:
and this is the Spring Boot error:
WARN 10289 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of `navid.usermanagementsys.domain.Company` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"id":26,"version":0,"dateCreated":"2018-08-08T16:02:15.000+0000","name":"company1","description":"Description Description Description Description","address":"IRAN","adminName":"Company admin","admin":{"id":25,"version":0,"dateCreated":"2018-08-08T16:02:15.000+0000","username":"company","password":null,"encryptedPassword":"$2a$10$kw5T5CCep.WwC5kj7Szgyu6akB7Zbx.jgqIz5dQtAx6Oz4F8ywIWq","enabled":true,"dateLastUpdated":"2018-08-08T16:02:15.000+0000"},"dateLastUpdated":"2018-08-08T16:02:15.000+0000"}');
nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `navid.usermanagementsys.domain.Company` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value** ('{"id":26,"version":0,"dateCreated":"2018-08-08T16:02:15.000+0000","name":"company1","description":"Description Description Description Description","address":"IRAN","adminName":"Company admin","admin":{"id":25,"version":0,"dateCreated":"2018-08-08T16:02:15.000+0000","username":"company","password":null,"encryptedPassword":"$2a$10$kw5T5CCep.WwC5kj7Szgyu6akB7Zbx.jgqIz5dQtAx6Oz4F8ywIWq","enabled":true,"dateLastUpdated":"2018-08-08T16:02:15.000+0000"},"dateLastUpdated":"2018-08-08T16:02:15.000+0000"}')
at [Source: (PushbackInputStream); line: 1, column: 152] (through reference chain: navid.usermanagementsys.domain.Personnel["company"])
I have spent hours searching for a solution and I have tried creating constructor with no args but nothing solved my problem.