Candlepin outputs JSON using JAXB. There is a limitation in what JAXB can ‘figure out’ when it comes to returning Lists of objects.
Returning a List of objects doesn’t quite work.
@GET @Path("/listobjects")
@Produces(MediaType.APPLICATION_JSON)
public List<Object> listObjects() {
return ObjectFactory.get().listObjectsByClass(getApiClass());
}
This results in an error, because there is no writer for Objects and JAXB doesn’t know that it is really a User.
A message body writer for Java type, class
java.util.LinkedList, and MIME media type, application/json, was not found
It is useful to return your model using a List of the base classes i.e. List
@GET @Path("/listbasemodel")
@Produces(MediaType.APPLICATION_JSON)
public List<BaseModel> listUsers2() {
List<Object> u = ObjectFactory.get().listObjectsByClass(getApiClass());
List<BaseModel> users = new ArrayList<BaseModel>();
for (Object o : u) {
users.add((BaseModel)o);
}
return users;
}
Unfortunately, this results in JSON being output for just the base class and does not try to determine the actual type of the class in this case User object. The resulting JSON shows what you get:
{"baseModel":[null,
null,
{"uuid":"78ff6590-ae2d-4926-901a-b650a4142399"},
{"uuid":"0c7b5169-cfe5-4916-ae47-1de066a3102d"}]}
Create a wrapper class for the List of objects. Here is Users which wraps a List<User>.
@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Users {
@XmlElement(required = true)
public List<User> userList;
}
The GET method is done as follows:
@GET @Path("/listusers")
@Produces(MediaType.APPLICATION_JSON)
public Users listUsers() {
List<Object> objects = ObjectFactory.get().listObjectsByClass(getApiClass());
Users users = new Users();
users.userList = new ArrayList<User>();
for (Object o : objects) {
users.userList.add((User)o);
}
return users;
}
This will yield the correct JSON output:
{"userList":[{"login":"test-login","password":"redhat"},
{"login":"test-login","password":"redhat"},
{"uuid":"78ff6590-ae2d-4926-901a-b650a4142399","login":"candlepin","password":"cp_p@s$w0rd"},
{"uuid":"0c7b5169-cfe5-4916-ae47-1de066a3102d","login":"candlepin","password":"cp_p@s$w0rd"}]}
Returning a list of the actual objects works as expected as well:
@GET @Path("/uselist")
@Produces(MediaType.APPLICATION_JSON)
public List<User> listUsers1() {
List<Object> u = ObjectFactory.get().listObjectsByClass(getApiClass());
List<User> users = new ArrayList<User>();
for (Object o : u) {
users.add((User)o);
}
return users;
}
This code results in the following JSON:
{"user":[{"login":"test-login","password":"redhat"},
{"login":"test-login","password":"redhat"},
{"uuid":"78ff6590-ae2d-4926-901a-b650a4142399","login":"candlepin","password":"cp_p@s$w0rd"},
{"uuid":"0c7b5169-cfe5-4916-ae47-1de066a3102d","login":"candlepin","password":"cp_p@s$w0rd"}]}