Hari Menon
Hari Menon

Reputation: 35405

Handling full and partial views in jersey for a REST API

I am working on creating a RESTful API for a project. I am facing a few problems trying to implement it with jersey:

  1. My object model does not contain uri info obviously. e.g, lets say I have a Fruit class. Fruit object would have let's say a FruitName and a FruitColor. But in the response I also need to send a URI. How is this usually handled? Should I create a separate "FruitResource" that has a constructor which takes a "Fruit" and creates a full resource from it, including URI? I need URIs in the nested objects as well, e.g if I am returning a list of Child objects, I need each Child object to also have a URI, but I donlt want the URI to be part of the object model. What is the cleanest way to do this?

  2. I want to have capability to return full and partial views of the same resource. Partial views would just have the name and the URI for example. How to get this done?

Right now what I have is a Service class that accepts the requests, which uses the DAO to create and return the objects as they are modelled from the DB, serialized to JSON using jackson.

Upvotes: 1

Views: 1882

Answers (4)

Hari Menon
Hari Menon

Reputation: 35405

Thanks for all your responses. Going through all the approaches you guys presented and after a little bit of research on my own, this is what I settled on:

1) I am adding uri as part of the object model. This seems to be the cleanest solution to me currently. The URI can be automatically populated whenever the object is created (using other properties of the object). Earlier I thought this is a bad idea, but I am not able to foresee any problems with this approach other than the extra field that will have to keep moving with the objects.

2) For supporting full/partial views, I am trying to use the @JsonView annotation. This seems to be a good approach.

Let me know if there are any other potential issues with this way of handling things.

Upvotes: 0

Solomon Duskis
Solomon Duskis

Reputation: 2711

I'm working on a project that supports both of those concerns: https://github.com/skyscreamer/yoga with more information at http://yoga.skyscreamer.org/, including a demo.

It replaces the JAX-RS (or Spring MVC) rendering mechanism with a custom built solution that's more in tune with the needs of a REST System.

For #1, we have an annotation that you have to apply to your Child pojo. JAX-RS's annotations are meant to map URLs to controllers not to the underlying object, so we needed a custom solution... but it's really just comes down to 1 additional annotation per pojo.

For #2, we have a URL based mechanism of specifying which additional information you want from a pojo or a pojo's children (and can be nested further).

I hope this helps.

Upvotes: 2

condit
condit

Reputation: 10962

1) I'm not aware of any Jersey or JAX-RS mechanism supporting this. Seems like a bad practice to have to add the URI to the constructor for each of your domain classes, though. You could create an aspect that would intercept the method and wrap the response in a new object - adding the URI of the resource in the wrapper (you could get the URIInfo via reflection from the interceptor). I've done this when building etag support so I don't have to add cache code to every response. I suppose you could also add something in the same aspect to handle the child URI issue...

You might also want have a look at these dicussions:

2) For building "lighter" response entities I typically have a BeanLite.class with just the properties I need for a summary and then a Bean.class extending it with more detail. You can add both to your ORM and provide an option to switch representations in your DAO.

Upvotes: 1

R H
R H

Reputation: 397

There i a way to use JaxB class and you can pass Object Model to JaxB class and JaxB class generates URI. The below is small prototype.

UserResource Class

@Path("/user")
public class UserResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{user-id}")
public UserJaxB getUser(@PathParam("user-id") String userId, @Context
HttpServletRequest request) {
    // now XYZ is hard-coded value 
    String serviceEndpoint = request.getContextPath() + "/" + "user";
    UserModel userModel = new UserModel(userId, "XYZ");
    return new UserJaxB(serviceEndpoint,userModel);
}
}

User JAXB Class

@XmlRootElement
public class UserJaxB {

private String name;
private String id;
private String serviceEndpoint;
private String URI;

public UserJaxB(String serviceEndpoint, UserModel userModel) {
    this.name = userModel.getName();
    this.id = userModel.getId();
    this.serviceEndpoint = serviceEndpoint;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getURI() {
    return this.serviceEndpoint + "/" + id;
}
}

User Model Class public class UserModel {

String name;
String id;

public UserModel(String name, String id) {
    this.name = name;
    this.id = id;
}

public String getId() {
    return id;
}


public String getName() {
    return name;
}
}

Upvotes: 2

Related Questions