I am pretty new to REST programming.
Below is my class which is intended to return XML/JSON but I am having some difficulties to make it return proper values. I tried returning Response, JsonArray
and Object of my POJO
class but its not working. I looked several threads but not able to figure out what exactly is the problem.
The resource class:
public class UserService {
UserDBHandler userDBHandler;
Friend f;
@GET
@Path("users/{userId}/friends")
// @Produces(MediaType.TEXT_PLAIN)
@Produces({ MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
public Friend getFriends(@PathParam("userId") String userId) throws SQLException, ClassNotFoundException
{
System.out.println("userId : " +userId);
userDBHandler = new UserDBHandler();
f = new Friend();
ArrayList<String> userList = userDBHandler.fetchUsers(userId);
System.out.println("Array size: "+userList.size());
Iterator<String> iterator = userList.iterator();
while(iterator.hasNext())
{
f.setUri(iterator.next());
System.out.println(f.getUri());
}
//JsonObject object = Json.createObjectBuilder().add("frienduri",f.getUri()).build();
//ResponseBuilder response = Response.ok(f);
//return Json.createArrayBuilder().add(object).build()
//return response.build();
return f;
}
}
The POJO class:
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
@XmlRootElement
public class Friend{
private String friendURI;
private String event;
private String uri;
String getUri() {
return uri;
}
void setUri(String uri) {
this.uri = uri;
}
String getFriendURI() {
return friendURI;
}
void setFriendURI(String friendURI) {
this.friendURI = friendURI;
}
String getEvent() {
return event;
}
void setEvent(String event) {
this.event = event;
}
}
This is what I get when I return the Response or the Friend object:
**<?xml version="1.0" encoding="UTF-8" standalone="yes"?><friend/>**
And when returning JsonArray
this is what I get:
[{"frienduri":{"string":"b@b.com","chars":"b@b.com","valueType":"STRING"}}]
Another problem I am facing is: if I create a constructor I get below error:
A MultiException has 1 exceptions. They are:
1. java.lang.NoSuchMethodException
: Could not find a suitable constructor in repository.resources.UserService class
.
My dev environment is Tomcat 8 , JDK 1.8, Eclipse Luna.
I am not using Maven or web.xml instead I have an Application class.
I am using jaxrs-ri-2.13 and jackson jars:
- jackson-core-asl-1.9.2
- jackson-jaxrs-1.9.2
- jackson-mapper-asl-1.9.2
- jackson-xc-1.9.2
Json jars
- javax.json-api-1.0
- javax.json-1.0.4
Thanks
First thing you should understand is that JAX-RS is a specification, and that jar you have
jaxrs-ri-2.13
is an implementation (actually the reference implementation) from Jersey. Knowing the implementation is important in helping to solve your problem. So you should mention this in your post (through a tag or explicitly).Second, for serialization, JAX-RS requires
MessageBodyReader
s andMessageBodyWriter
s. Jersey distribution has support for xml out the box, but for JSON we need to add a module with for support. Jackson by itself does not provide support for this. We need a provider module likejersey-media-jason-jackson
. Using Maven is the easiest way to get this module, as it is dependendent on other jars. If I create a new Maven project, with only this dependency, this is the complete list, of artifacts the the module is dependent onThe Jersey distribution has some of these artifacts already. I am not sure if all of them are included in the bundle jar, but based on the main (un bundled) Jersey distribution, the un-shaded jars are not included
You will need to go looking for those jars and add them to your project. Like I said, I don't know if the Jersey Bundle jar comes with the others, packages, bu you can get the complete distribution here that uses individual jars. If using the single jar doesn't work, I would look into using the separate jars (all of them).
Adding these jars should give you
Friend
to JSON support.<?xml version="1.0" encoding="UTF-8" standalone="yes"?><friend/>
You need to make your
Friend
accessor methodspublic
. The writer cannot find thegetXxx
method as it's not in the same package. You should also make thesetXxx
methods public.Yup. The resource class is created by Jersey, which handles the lifecycle of our request scoped resource classes, and requires a
no-arg
constructor. Adding a constructor with arguments, cancels the implicit no-arg constructor. But even if you create a no-arg constructor and you other arg constructor, the arg constructor will never be called, unless you explicitly create the instance of your resource class as a singleton.UPDATE
When you extend
Application
, you can overridegetClasses()
(which will be container managed request scoped resource class) andgetSingletons
which will be a single instance for the entire applicationBut I am not sure if you really want
UserResource
to be a singleton. This means that you want this resource to be stateful for the entire application, which may not be desired. Instead you can use an injection framework, supported by Jersey, in order to inject theUserDBHandler
into theUserResource
class. Something likeSee more at Custom Injection. Also I just tested this with the single
jaxrs-rs
jar and it does not come with the needed classes. You will need to download the separate Jersey distribution (mentioned above) will all the single jars, and add all those jars to your project, for this to work, or at least include thehk
jars, which are also required by the Jackson provider anyway.