Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No primary or default constructor found for interface java.util.List Rest API Spring boot

I am passing a request body to a POST request on postman similar to this:

 "name":"Mars",
"artifacts":[
   {
      "elements":[
         {
            "name":"carbon",
            "amount":0.5,
            "measurement":"g"
         }
      ],
      "typeName":"typeA"
   },
   {
      "elements":[
         {
            "name":"hydrogen",
            "amount":0.2,
            "measurement":"g"
         }
      ],
      "typeName":"typeB"
   }
]

The create method in the rest controller looks like this.

  @RequestMapping("/create")
  public Planet create(@RequestBody Planet data) {
      Planet mars = planetService.create(data.getName(),data.getArtifacts());
      return mars;

Planet and all its nested objects have a default constructor such as:

public Planet() {}

However, I am not able to create a new planet object because of lack of a default constructor. Please help!

EDIT: Planet class

public class Planet {
@JsonProperty("name")
private String name;
@Field("artifacts")
private List<Artifact> artifacts;

public Planet() {}

public Planet(String name, List<Artifact> artifacts)
{
this.name = name;
this.artifacts = artifacts;
}
//setters and getters

}

Artifact class:

public class Artifact() {
@Field("elements")
private List<Element> elements;
@JsonProperty("typeName")
private String typeName;

public Artifact() {}

public Artifact(String typeName, List<Element> elements)
{
this.typeName = typeName;
this.elements = elements;
}
}

Element class:

public class Element() {
@JsonProperty("elementName")
private String name;
@JsonProperty("amount")
private double amount;
@JsonProperty("measurement")
private String measurement;

public Element() {}

public Element(String name, double amount, String measurement)
{
//assignments
}
}
like image 459
Hermione Granger Avatar asked Feb 13 '19 05:02

Hermione Granger


4 Answers

I had that the same error when I forgot the @RequestBody before the parameter

  @RequestMapping("/create")
  public Planet create(@RequestBody Planet data) {
like image 115
Marc Avatar answered Oct 23 '22 04:10

Marc


I guess, it’s trying to call new List() which has no constructor. Try using ArrayList in your signatures.

If it works this way, you have found the error. Then rethink your concept of calling methods, since you would usually want to avoid using implementations of List in method signatures

like image 32
iPirat Avatar answered Oct 23 '22 04:10

iPirat


I don't understand what is the issue you are facing, but i can see an error straight away so guessing that is the issue you are facing, i am going to give you a solution.

Create a class which matches your json data structure like this :

Class PlanetData {
    private String name;
    private List<Planet> artifacts;

    public PlanetData(String name, List<Planet> artifacts){
        name = name;
        artifacts = artifacts;
    }

    // include rest of getters and setters here.
}

Then your controller should look like this. Basically you needed to put @RequestBody to all the parameters you want to recieve from request JSON. Earlier you only put @RequestBody to name parameter not artifact parameter and since Request Body can be consumed only once, so you need a wrapper class to recieve the complete request body using single @RequestBody annotation.

@RequestMapping("/create")
  public String create(@RequestBody PlanetData data) {
      Planet mars = planetService.create(data.getName(),data.getArtifacts());
      return mars.toString();
  }

Edit : Looking at the Planet class, it also needs some modification

public class Planet {
private String typeName; // key in json should match variable name for proper deserialization or you need to use some jackson annotation to map your json key to your variable name.
private List<Element> elements;

public Planet() {}

public Planet(String typeName, List<Element> elements)
{
this.typeName = typeName;
this.elements = elements;
}
//setters and getters. Remember to change your setters and getter from name to typeName.

}

Hope this solves your issue.

like image 8
Arpit Agrawal Avatar answered Oct 23 '22 03:10

Arpit Agrawal


This answer too might help someone.

When you are using spring framework for your API development, you may accidently import a wrong library for RequestBody and RequestHeader annotations.

In my case, I accidently imported library,

io.swagger.v3.oas.annotations.parameters.RequestBody

This could arise the above issue.

Please ensure that, you are using the correct library which is

org.springframework.web.bind.annotation.RequestBody
like image 2
shashika11 Avatar answered Oct 23 '22 04:10

shashika11