I am trying to save Parent (One) and Children (Many) entities at the same time.
I took help from here and here.
I have an User Entity like below:
@Entity
@Table(name = "app_user")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class AppUser {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "salutation")
private String salutation;
@Column(name = "name")
private String name;
@Column(name = "email")
private String email;
@Column(name = "preference")
private String preference;
public AppUser(String salutation, String name, String email, String preference, List<Address> addressList,
List<Expertise> expertise) {
super();
this.salutation = salutation;
this.name = name;
this.email = email;
this.preference = preference;
this.addressList = addressList;
this.expertise = expertise;
}
@OneToMany(orphanRemoval = true, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "address_id")
private List<Address> addressList = new ArrayList<>();
@OneToMany(orphanRemoval = true, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "expertise_id")
private List<Expertise> expertise = new ArrayList<>();
My POST controller method.
@PostMapping("/appUsers")
public ResponseEntity<AppUser> createUser(@RequestBody AppUser appUser) {
try {
AppUser _appUser = appUserRepository.save(
new AppUser(appUser.getSalutation(), appUser.getName(), appUser.getEmail(),
appUser.getPreference(), appUser.getAddressList(),
appUser.getExpertise()));
return new ResponseEntity<>(_appUser, HttpStatus.CREATED);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
My pure JS (Fetch) snippet:
<script>
async function postDataToServer(postData) {
const baseURL = "http://localhost:8080/api";
try {
const res = await fetch(`${baseURL}/appUsers`, {
method: "post",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(postData),
});
if (!res.ok) {
const message = `An error has occured: ${res.status} - ${res.statusText}`;
throw new Error(message);
}
} catch (err) {
alert(err.message);
}
}
</script>
Using above, I can see the form data nicely forming up like below:
{
"salutation": "Mr.",
"name": "Ajay Kumar",
"email": "ajay@kumar.com",
"address_main": "1234 StreetName State 12345",
"address_1": "2345 StreetName State 23456",
"address_2": "3456 StreetName State 34567",
"preference": "Vegeterian",
"expertise": [
"java",
"springboot",
"javascript"
],
"secret": "1abc1234-1abc-4321-1234-1234abcd1234"
}
During submit if I don't select expertise, it all works find. i.e. the user gets saved but if I select expertise checkboxes I get a 400 bad request message at the browser console and JSON parse erroSTS console like this:
2022-02-25 11:02:53.009 WARN 25007 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot construct instance of
com.spring.boot.rocks.model.Expertise
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('java'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance ofcom.spring.boot.rocks.model.Expertise
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('java') at [Source: (PushbackInputStream); line: 1, column: 234] (through reference chain: com.spring.boot.rocks.model.AppUser["expertise"]->java.util.ArrayList[0])]
I created a github project here if any more details are required.
Question: What I am missing? How do I convert expertise
collection to List using pure JS only ? Or how do I handle expertise
collection in controller?