Reputation: 2227
On the client app I have this POJO
public class Chicken {
private String name;
private int age;
public Chicken(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
and I run this
RestClient get = RestClient.create().method("GET")
.host("http://localhost:8080/DevCrowd")
.path("resources/chickens");
GluonObservableList<Chicken> sample = DataProvider.retrieveList(
get.createListDataReader(Chicken.class));
System.out.println(sample);
But I get the error:
WARNING: Failed to create object of type class com.devcrowd.test.Chicken from the following json object {"id":1,"name":"AAA","age":12}
java.lang.InstantiationException: com.gluonhq.notesapp.Chicken
at java.lang.Class.newInstance(Class.java:427)
at com.gluonhq.connect.converter.JsonConverter.readFromJson(JsonConverter.java:111)
at com.gluonhq.connect.converter.JsonIterableInputConverter.next(JsonIterableInputConverter.java:108)
at com.gluonhq.connect.provider.DataProvider.lambda$retrieveList$21(DataProvider.java:194)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoSuchMethodException: com.gluonhq.notesapp.Chicken.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 6 more
On the server I have this entity:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
@Entity
@NamedQuery(name="all", query = "SELECT c FROM Chicken C")
public class Chicken {
@Id
@GeneratedValue
private long id;
private String name;
private int age;
public Chicken() {}
public Chicken(String name, int age) {
this.name = name;
this.age = age;
}
}
and this service:
@Path("chickens")
public class ChickensResource {
@Inject
ChickenService cs;
@GET
@Produces(MediaType.APPLICATION_JSON)
public String chickens() {
JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
List<Chicken> chickens = cs.getAllChickens();
chickens.stream().map(chicken -> Json.createObjectBuilder()
.add("name", chicken.getName())
.add("age", chicken.getAge())
.build())
.forEach(jsonArrayBuilder::add);
return jsonArrayBuilder.build().toString();
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public void save(JsonObject chicken) {
String name = chicken.getString("name");
int age = chicken.getInt("age");
cs.save(new Chicken(name, age));
}
}
I can POST correctly (I check the DB and what I POST is there so this is why the error stack has a Chicken
object ready) but I can't read it back. Why is that?
Upvotes: 1
Views: 358
Reputation: 45476
As you can read in the docs for JsonConverter::readFromJson
:
Convert the provided JSON Object into a Java object. If a new instance could not be created from the specified targetClass in the constructor, then null will be returned.
The conversion works by inspecting all the property methods of the target class. A property method is any field that has both a getter and a setter method.
Now if you check your exception:
java.lang.InstantiationException: com.gluonhq.notesapp.Chicken
at java.lang.Class.newInstance(Class.java:427)
the reason becomes clear: the target class (com.gluonhq.notesapp.Chicken
) can't be instantiated, because it looks for a parameterless constructor.
All you'll need to do is add one:
public class Chicken {
private String name;
private int age;
public Chicken() { }
public Chicken(String name, int age) {
this.name = name;
this.age = age;
}
...
}
EDIT
The DataProvider
returns an observable list, and you should use the initializedProperty()
to find out when the list is ready, so you can get its content:
RestClient get = RestClient.create().method("GET")
.host("http://localhost:8080/DevCrowd")
.path("/resources/chickens");
GluonObservableList<Chicken> sample = DataProvider.retrieveList(
get.createListDataReader(Chicken.class));
sample.initializedProperty().addListener((obs, ov, nv) -> {
if (nv) {
for (Chicken chicken : sample) {
System.out.println(chicken);
}
}
});
Upvotes: 1