Showing posts with label JSON. Show all posts
Showing posts with label JSON. Show all posts

Thursday, January 12, 2012

JAX-RS Tip of the Day: Client Content Negotiation

One of the less discussed aspects of JAX-RS based on the HTTP 1.1 specification is client negotiation. We often write our applications from the server side and expect the client to send us an Accept: */* header which details which media types the client can accept. The server simply returns whatever we have coded for example @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}). However I bet a number of you have seen something like this before:
http://www.example.com/documents/mydoc?format=doc
http://www.example.com/documents/mydoc.xml
The first example is not very subtle. It tells you the client wants a mydoc.doc by requesting a specific format. The second example is more subtle, and the end user (client) may not notice. I made it a "little" more obvious by changing it to .xml. However, most folks would have missed it if I used mydoc.doc. You would have assumed it was a MS Word document to start with. In actuality, the media type returned here is controlled by the file extension.

Note: Updated the source code to include header based negotiation, but this is just mimicking server content negotiation.

In the attached Apache Maven project developed on NetBeans 7.1: jersey-content-negotiation.zip. I demonstrate how to do it.

The first example returns JSON by default, and other media formats as requested. If it does not understand the media type requested, it simply returns plain text.

On the second example which uses the media type extension, I return a 400 - Bad Request instead of plain text like the first example. This subtlety is based on the fact that the client is requesting a specific type based on extension. If you ask for .pdf and get .txt, the result may cause an unanticipated consequence so it is better to throw an exception.

The mixed media type returns are possible because of the Response being wrapped as demonstrated in a previous post: JAX-RS Tip of the Day: Use Response to wrap... Responses.

ContentNegotiationResource.java



Client Negotiation Examples

Wednesday, January 11, 2012

JAX-RS Tip of the Day: Use Response to wrap... Responses

One of the really nice features of JAX-RS is the ability to implement fine grained control over the response returned from the server based on the client request. The Response.ResponseBuilder gives us incredible flexibility to generate the response. Since it uses the builder pattern, it is easy to daisy-chain the information we want into a custom response.

I would highly recommend that you consider returning a custom response for all requests. I would like to explain with an example. I would like to perform a @POST request where I am creating a new object on the server. Since it is a HTTP 1.1 request, I look at Hypertext Transfer Protocol -- HTTP/1.1 (RFC-2616) to see what I must, should, and may return. The difference in the word choices has specific meaning in the specification. In my case, I would like to be completely compliant.

10.2.2 201 Created
The request has been fulfilled and resulted in a new resource being created. The newly created resource can be referenced by the URI(s) returned in the entity of the response, with the most specific URI for the resource given by a Location header field. The response SHOULD include an entity containing a list of resource characteristics and location(s) from which the user or user agent can choose the one most appropriate. The entity format is specified by the media type given in the Content-Type header field. The origin server MUST create the resource before returning the 201 status code. If the action cannot be carried out immediately, the server SHOULD respond with 202 (Accepted) response instead.
A 201 response MAY contain an ETag response header field indicating the current value of the entity tag for the requested variant just created, see section 14.19.

OK, the basic response must return 201 - Created status, and a Location header. It should contain an entity (which may only be entity-headers) and may contain an ETag. This is all very easy to do with Jersey. As you can see from the code snippet, we read the @FormParam information from a form, and create an object which we add to a List<Widget%gt; objects signified by the ws.add(widget) we get the index value for use in our URI. Next we create a URI from our request, and add a path to it for our index.

Finally we use Apache Commons Codec Hex to generate a hex string for our ETag. Finally this is all combined in a Response sent back to the client. This can be seen below.

Tuesday, January 10, 2012

Interesting Articles on JAX-RS

What do I Read?

I was asked what articles I really like on Jersey, and how to learn more about it. Here is an incomplete list.

If you find more really good ones, please post comments, and I will add them to the list if I like them.

Thursday, January 05, 2012

JAX-RS Tip of the Day: Using @CookieParam

I am not a fan of using cookies in REST based services. I think that it makes the service less usable since the client must be able to store and retrieve cookies. This limits usage of the service, and introduces state outside of the service. Even the RFC for cookies is called HTTP State Management Mechanismcurl can be used to send cookies to test so not all is lost.

Alright, if I have not talked you out of using them yet, you must have a need for them.  (Please rethink the idea though).

Use of cookies is accomplished by using the @CookieParam annotation. Also you can return responses as shown in the code below which include cookies.

Cookies have a limitations on the use of some characters, and names so please look at the RFC noted above for additional limitations. I demonstrate a couple of limitations which include the use of semi-colons (;), and commas(,). The nice thing about this example is you can see the output in a real browser (Internet Explorer not included) since most can handle application/json objects which are returned.

Here is the example code developed using NetBeans 7.1 RC2 and GlassFish 3.1.1cookie-parameters.zip

CookieParameterResource.java


Saturday, December 31, 2011

JAX-RS Tip of the Day: Using YUI2 and YUI3 DataTables with Jersey and jQuery

This is a great example (if I do say so myself) that demonstrates some really cool capabilities of Jersey combined with Yahoo User Interface versions 2 and 3 combined with jQuery to demonstrate interoperability of multiple technologies.

The example code that I have included uses GlassFish 3.1.1 with Jersey 1.11 and was developed using NetBeans 7.1 RC2. The data is from the default sample database included in NetBeans. Here is the code: jsonp-database.zip

The YUI2, YUI3, and jQuery libraries are provided by Yahoo and Google CDN. This is a further example of a truly RESTful application where the application is provided as a mashup of multiple web resources.

Yahoo User Interface (YUI) is an incredibly well developed UI framework for the web. The DataSource implementation is easy to use and is extremely adaptable. It is also very stable, and Yahoo eats its own dogfood like Google so it is battle tested. YUI3 is the next generation code, and the DataTable implementation includes a number of new features.

jQuery is an extremely popular Javascript framework with great AJAX functionality. I have included two examples (YUI2/YUI3) in which jQuery provides JSON data to the Yahoo DataSource.

Jersey provides the heavy lifting. In all of the examples I provide the data in a variety of formats, but I focus on providing both JSON and JSONP. JSONP allows us to use have cross-domain capabilities. The code also demonstrates how to use Jettison to encapsulate POJOs. The best part is that the data can be tested not only using your browser, but can also be tested using curl. This provides a very simple visual means of verifying data.

So what does it look like... look at the images below. The results speak for themselves.

YUI2 DataTable using JSP

YUI3 DataTable with JSONP and JAX-RS (Jersey)

Now for the most important part, how do you get here.

Technical Details

The CustomerFacadeREST class is the most interesting. The JSP and HTML pages have the details of how to use the various YUI DataSources along with jQuery. I will not print the pages out, and suggest that you simply download the code and examine it.

CustomerFacadeREST.java



CODE


Here is the code: jsonp-database.zip

JAX-RS Tip of the Day: Changing JSON-JAXB Default Mapping

JSON-JAXB marshalling and un-marshalling by default uses a MAPPED configuration by default. However this can be changed by creating a @Provider which can change the default JSONConfiguration.

The example below changes the configuration to use BadgerFish which provides a better representation of an XML document. This representation does not provide the visual clarity that JSON generally provides, and is not generally human readable beyond basic notation. However, as noted that is not the point.

JSONJAXBContextResolver.java


This class specifically handles the Customer object, and maps it to use BadgerFish. Output:

Friday, December 30, 2011

JAX-RS Tip of the Day: Automatic Mapping of Jettison JSON Objects

One of the more interesting features in JAX-RS (Jersey) is the ability to automatically "wrap" POJOs. This combined with automatic wrapping of JAXB annotated beans, and using Jackson to create JSON objects is a powerful mix. However, sometimes we want to wrap an object, and add some additional metadata.

This tip is a very simple tip which allows you to create Jettison JSONObject, and JSONArray objects to create new objects, "wrap" existing objects, or add additional metadata. I mention "wrap" the objects, please don't confuse this with JSONP.

To enable automatic POJO mapping, and Jettison objects add the following to the web.xml
This simple configuration will give you considerable flexibility in how you handle your objects. This will now allow you to produce JSONObjects like the code example below:

Popular Posts