Reputation: 2065
What would you say to be the best approach when designing a web service that is supposed to return different representations (such as JSON, XML) of the same data.
The requirement would be to have the business logic completely separated from the part that writes the actual XML/JSON response, depending on the "Accept" header received in the HTTP request.
I figure this is a common problem which many web services have. Any tips/design patterns/wikis/projects you could help me with?
Upvotes: 2
Views: 1142
Reputation: 634
Another approach:
You can declare your service method with multiple return types (MediaTypes) as described below:
@Path("/root")
public class GetDetailsService{
@GET
@Path("/getDetails")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Todo getDetails() {
Todo todo = new Todo(); // Todo is just a pojo return type which would finally be converted into either XML or JSON type based on the "Accept" header of your HTTP request.
todo.setSummary("This is my first todo");
todo.setDescription("This is my first todo");
return todo;
}
}
public class Todo {
private String summary;
private String description;
// Getters and Setters
}
Now, a JSON type or an XML type would be returned based on the "Accept" header of your HTTP request.
Upvotes: 1
Reputation: 634
Include a new delegate layer in your application which delegates all your requests to your service layer. In your ServiceDelegator class you can have multiple methods (with different return types) which inturn invoke the target method of your service. Your business method would be there in your service class where as multiple methods of your ServiceDelegator class would invoke the same business method of your service.
@Path("/root")
public class ServiceDelegator{
@GET
@Path("/getDetailsAsXML")
@Produces(MediaType.APPLICATION_XML)
public Todo getDetailsAsXML() {
return new GetDetailsService().getDetails();
}
@GET
@Path("/getDetailAsJSON")
@Produces(MediaType.APPLICATION_JSON)
public Todo getDetailsAsJSON() {
return new GetDetailsService().getDetails();
}
}
public class GetDetailsService{ // your service class containing the business methods
public Todo getDetails() { // Todo is just a pojo return type which would finally be converted into either XML or JSON type based on the delegator method that invoked this service
Todo todo = new Todo();
todo.setSummary("This is my first todo");
todo.setDescription("This is my first todo");
return todo;
}
}
public class Todo {
private String summary;
private String description;
// Getters and Setters
}
Upvotes: 1
Reputation: 5085
First question is which HTTP protocol you would like to use: REST or SOAP?
When using REST, I would create one service, with different consumer methods for every representation. Behind this REST service, you can have your real service and the consumer methods call exactly the same business logic. You can modify your path according to the representation you want to be returned.
For example:
@GET
@Path("/json/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response readAsJson(@PathParam("id") String id) throws JAXBException {
final Object obj = dao.get(id);
if (obj == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
return Response.ok(obj).build();
}
@GET
@Path("/xml/{id}")
@Produces(MediaType.APPLICATION_XML)
public Response readAsXml(@PathParam("id") String id) throws JAXBException {
final Object obj = dao.get(id);
if (obj == null) {
return Response.status(Response.Status.NOT_FOUND).build();
}
return Response.ok(obj).build();
}
Upvotes: 3