0

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 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') 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?

ℛɑƒæĿᴿᴹᴿ
  • 4,983
  • 4
  • 38
  • 58
Ajay Kumar
  • 2,906
  • 3
  • 23
  • 46
  • In AppUser expertise is List, but in json you send expertise as List. Change JS code. You should get something like ... "expertise": [{"expertise": "java"}, {"expertise": "sprringboott"}] ... Or (in Java code) change expertise,s type to List – Nenad J. Feb 25 '22 at 16:42
  • Can you please post the pseudo code. I am lost. – Ajay Kumar Feb 25 '22 at 17:08
  • Sorry for late response. Your json is incorrect. You should send something like this: { "salutation": "Mr.", "name": "Ajay Kumar", "email": "ajay@kumar.com", "addressList": [ {"address": "1234 StreetName"}, {"address": "2345 StreetName"}, {"address": "3456 StreetName"}], "preference": "Vegeterian", "expertise": [ {"expertise": "java"}, {"expertise":"springboot"}, {"expertise":"javascript"} ], "secret": "1abc1234-1abc-4321-1234-1234abcd1234" } You have problem with address, also. Try to test REST api with postman – Nenad J. Mar 01 '22 at 08:27

1 Answers1

0

Your form data is not in correct format. This should be like this:

{
  "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"
}

Expertise and address in your parent class are lists, not normal objectType entity. If any of these two lists are not present, try to set them as emptyList before saving.

user404
  • 1,934
  • 1
  • 16
  • 32
  • I am not able to follow. expertise will carry only one set of strings at a time like so: "expertise": [ { "java", "springboot", "javascript" }]. I am confused. – Ajay Kumar Feb 25 '22 at 20:10
  • @AjayKumar, no worries, I have updated my answer, please check it. What I am trying to tell is that, your son format in the question is wrong but what you have wrote in the comment is correct. please do accordingly – user404 Feb 26 '22 at 05:20