users@jersey.java.net

Re: [Jersey] Best practices for client specific serialization customization

From: Kevin Duffey <andjarnic_at_yahoo.com>
Date: Fri, 10 Oct 2008 09:47:25 -0700 (PDT)

I still think having an optional query parameter exactly like Victor's example would work best. For example... if you wanted to get a subset, the mobile client could pass in the query parameter with the range it wants. Mean while, the same service can be used by a desktop application with no query parameter to get the full list. You could use two query parameters perhaps... one to allow an optional range, and one to specify the "depth" of the response.. maybe your mobile client would do something like: GET /employees?range=1,5&depth=1 This might return something like: <employees> <employee> <id>123</id> <firstName>John</firstName> <lastName>Doe</lastName> </employee> <employee> <id>234</id> .. </employee> .. .. .. <employees> Just the first/last/id. The desktop app might make this cal: GET /employees and get: <employees> <employee> <id>123</id> <firstName>John</firstName> <lastName>Doe</lastName> <address> <street>Abc 123</street> <city>New York</city> <zip>12345</<zip> </address> <department> <id>123</id> <name>Marketing</name> <parentDepartment> <id>234</id> <name>Corporate Services</name> <parentDepartment> <id>345</id> <name>Acme Ltd.</name> </parentDepartment> </parentDepartment> <department> </employee> <employee> <id>234</id> .. </employee> .. .. .. <employees> Same service... one uses query parameters that your service checks for... the other just says "give me all of it, full depth". You could default the "depth" of the response to just the minimal set, and require optional parameter(s) to get more details. We could reverse the above logic, make the simple GET return minimal info, and require a query parameter to specify more details: GET /employes?includes=address,department which you would use @QueryParam("includes") and tokenize on the comma. Each item could be matched to some subset of data you include in the response. In this way, you're not using a param name like depth which isn't very informative of what it is doing, and you're using direct names in the comma separated list of the parts (objects) that you want in response. Even better, as a fellow colleague pointed out, this allows you to add new types of data and not break backwards compatibility. If you added a new object "salary", existing applications would not know its available and still work.. new apps could simply add that to the query and get more info back. In this way, the GET /employees by itself would return just the minimal data, and you request for more data if you want it. It's the opposite of what I said above.. it's probably more a matter of taste. I personally like the minimal info back, and request more details if I need them. This is more inline with most applications that would display a minimal set of data, and when you click on it, it expands, pops up or whatever with more detailed data of the selected item. Like I said, I prefer this approach... it uses less bandwidth by default, and only when requested does more info get sent back. ----- Original Message ---- From: "Kytömäki, Janne" <janne.kytomaki_at_logica.com> To: "users_at_jersey.dev.java.net" <users_at_jersey.dev.java.net> Sent: Thursday, October 9, 2008 4:34:41 AM Subject: [Jersey] Best practices for client specific serialization customization Hi, Since Victor got an answer for best practices for JAX-RS paging, I'll give it a shot too with different problem. :-) Objects serialized and returned by JAX-RS services may be complex and have lots of nested objects, thus an XML serialized list of just a few objects can weight tens or hundreds of kb's. Some clients, like a web AJAX application with large screen estate, may find all of this data useful and have no problem with even large file transfers, whereas other clients, such as a mobile application, might prefer getting only a subset of data per object that it can quickly (and cheaply) download and fit on its limited screen and then get the details for a particular object when needed via a subsequent JAX-RS request. It feels a bit cludgy to implement separate JAX-RS services for example for the AJAX and the mobile application, one that would return the full object trees and one that would only return limited versions of the objects. Does anybody have any ideas how one should make the object serialization customizable by the client with JAX-RS while using the same service and same source objects? Perhaps the client should define required object properties in the request and these should be passed to the JAXB binding process somehow in the service? Example: Let's say we have a JAX-RS service /employees/ that returns a list of all employees for a company. An example of returned document in XML format: <employees> <employee> <id>123</id> <firstName>John</firstName> <lastName>Doe</lastName> <address> <street>Abc 123</street> <city>New York</city> <zip>12345</<zip> </address> <department> <id>123</id> <name>Marketing</name> <parentDepartment> <id>234</id> <name>Corporate Services</name> <parentDepartment> <id>345</id> <name>Acme Ltd.</name> </parentDepartment> </parentDepartment> <department> </employee> <employee> <id>234</id> .. </employee> .. .. .. <employees> The example AJAX application client prefers this full object serialization, but the limited mobile client would prefer only getting the employee id's and names to populate a list, and when required (i.e. user selects an employee on the list), it would then call /employee/{id} to get the details for a particular employee: <employees> <employee> <id>123</id> <firstName>John</firstName> <lastName>Doe</lastName> </employee> <employee> <id>234</id> .. </employee> .. .. .. <employees> Thanks, Janne