Sunday, October 2, 2011

Describing JSON Services in WADL

WADL can describe RESTful XML services really well, by having request and response representations linked to corresponding XML or Relax NG schema element declarations.
However, you've most likely seen the following fragments showing that both XML and JSON representations are supported:

<response>

<representation
mediaType="application/xml"
element="ns:Book""/>
<representation
mediaType="application/json"/>
</response>



The above fragment can describe a method like this one:

@GET
@Produces(
{"application/xml",
"application/json"})
public Book getBook() {...}



So given the WADL fragment above, the consumer can get an idea of how an XML response will look like, and thus how to consume and possibly validate it. The description of the JSON response representation gives no information at all.

That is not fair I can hear you, JSON fans, saying :-). Or perhaps I can hear people saying WADL is not good enough for describing JSON services. But CXF makes things possible :-), and hopefully the following two recent updates can help:

1. Setting a linkJsonToXmlSchema property on CXF WADLGenerator will result in a fragment like this one be created:


<response>

<representation
mediaType="application/xml"
element="ns:Book""/>
<representation
mediaType="application/json"/>
element="ns:Book""/>
</response>



Well, describing JSON representation with XML schema is not technically correct, but more often than not an XML schema element instance will give a pretty good idea how a JSON will look like, for example, a Book bean can be used to generate both XML and JSON sequences by the providers in charge.

Update: CXF WadlToJava generator has been updated to handle WADL representation elements with the "application/json" media type which link to XML Schema elements.

2. Setting HTTP Accept header to application/json when requesting WADL will result in a WADL JSON representation returned. For example, given

?_wadl&_type=json


will return a JSON-format WADL instance. Is that really cool ? You bet it is. What about WADL grammar referencing XML schemas, does it really make sense to JSON-format XML schemas ? No it does not, but we have a JSON schema initiative so what you need to do is just configure WADLGenerator to reference a schema like the one describing Products in this section and here you go. For example:

WADLGenerator wg = new WADLGenerator();
wg.setSchemaLocations(
Collections.singletonList("json.schema"));
// do not create JAXB context
wg.setUseJaxbContextForQnames(false);
// let JSON provider handle it
wg.setIgnoreMessageWriters(false);


The provider can have the above properties set from Spring if needed.
The reference to the json.schema will be replaced with an absolute URI so the consumer handling a WADL JSON representation will be able to GET the referenced schema in the follow-up request.

For the above approach to become of some practical use, the tooling support is important. Consider opening a JIRA in the SoapUI project, vote for it and see what happens :-).

Enjoy !

6 comments:

saki said...

Your comment

"Setting HTTP Accept header to application/json when requesting WADL will result in a WADL JSON representation returned. For example, given

?_wadl&_type=json


will return a JSON-format WADL instance"

Does not seem to be true (this is with properly annotated methods with @Produces{"application/xml",
"application/json"})). I've tried this with CXF versions 2.4.0, 2.4.6, and 2.5.2. In the 2.4.x versions, an XML formatted WADL is returned and in 2.5.2, "[#document: null]" is returned.

Is there an additional piece of configuration that must be done?

saki said...

Your comment

"Setting HTTP Accept header to application/json when requesting WADL will result in a WADL JSON representation returned. For example, given

?_wadl&_type=json


will return a JSON-format WADL instance"

Does not seem to be true (this is with properly annotated methods with @Produces{"application/xml",
"application/json"})). I've tried this with CXF versions 2.4.0, 2.4.6, and 2.5.2. In the 2.4.x versions, an XML formatted WADL is returned and in 2.5.2, "[#document: null]" is returned.

Is there an additional piece of configuration that must be done?

Sergey Beryozkin said...

You need to explicitly configure WADLGenerator as suggested in the code fragment and then register is as a jaxrs:provider. There has to be a link to the JSON formatted schema. This is supported starting from CXF 2.5.x

Anonymous said...

Can you post the json schema used in WADL here

Sergey Beryozkin said...

For example, http://svn.apache.org/repos/asf/cxf/trunk/rt/rs/extensions/providers/src/test/resources/json.schema

Sergey Beryozkin said...

Note, "linkJsonToXmlSchema" property is needed if you'd like to have XML schema generated which is not needed if you need WADL doc in JSON format.

Lets continue the conversation on the CXF users list.