News and Notes from the Makers of Nexus | Sonatype Blog

Documenting the Nexus REST API with Enunciate

Written by Tamas Cservenak | February 08, 2010

Nexus OSS Core has more than 120 REST Resources published. And that number is just increasing with new Nexus Plugins. Not to mention Nexus Pro that comes with even more plugins and more REST resources. Everything you do in Nexus, whether you use the Maven Nexus plugin or the Nexus UI, is interacting with a REST service that is available to you if you want to write your own customizations and scripts. It has been this way since we started the project in 2007. In this post, I'm going to discuss how this came to be, how Nexus was developed with REST in mind from the beginning.

Nexus: A Core of REST Services

When we started the Nexus project, I called it a "blind" application. A "blind" webapp is one with no UI technology whatsoever built-in. All it publishes is a few static files, and a REST API. All of the UI that you see in Nexus is Javascript. Your browser executes Javascript which, in turn, interacts with a set of services. The only presentation technology on the server side is a trivial Velocity template used to render the initial "shell" of the page.

The server-side application you call Nexus, doesn't generate the UI, that is all Javascript. It is a completely separate and standalone application, that runs in your browser! A self contained JavaScript application (powered by ExtJS), that communicates with Nexus server, using REST calls only. This has one very important consequence: whatever Nexus functionality you are able to reach using the Nexus User Interface (and I do mean all), you can do with a plain REST client. If you want to automate a task, you can use a tool like curl, or some Ruby script, or any HTTP capable client. You can even start to implement your own custom interface if you would like a completely customized UI.

As I said, it was like this since day one. But, we always had one major issue that prevented wider acceptance of Nexus' REST API: we had no up-to-date documentation for it. It wasn't a priority, we spent much of our time trying to integrate the only existing REST framework (restlet.org) with Plexus, and since we were moving so quickly to implement new features, we didn't think it made sense to stop and document an ever-changing interface. We did maintain a wiki page which described the REST services from the beginning of the project, it always provided stale information given our aggressive development pace.

REST Documentation: Using Enunciate

I've been looking at the Enunciate project for some time, and it appears to be the solution to our REST document issues. Enunciate is a cool project hosted on Codehaus, with a bold promise:

Enunciate is designed to make your life easier. Enunciate deals with your deployment difficulties, documentation, and client-side code. By using Enunciate to publish your service interfaces, not only will you have all three Web service interfaces (SOAP, REST, and AMF), but you'll also have full up-to-date documentation generated, strongly typed ActionScript code that you can use to invoke your remote services from your Flex code, and rich client-side libraries that can be used to access your Web services from a variety of platforms (including Mac/iPhone).

Our initial plans are to use Enunciate in a "lite" mode to generate documentation (and potentially client side code) for our current REST API. Later, we plan to integrate it more closely into new Nexus "Remoting API" implementation, and it will be the backbone of our REST services when we will implement version 2.0 of our API.

Here is just a taste of what is to come. We've used Enunciate to generate documentation for our REST services, and the work is proceeding very quickly. Here is a snapshot of the documentation we will be releasing soon.

Remaining Problems to Solve

When our REST API was concieved in Q4 of 2007 we didn't have the rich array of options that we have today. One major REST library was available, and that was Restlet. JSR311 wasn't around back then, so we were forced to code directly to the Restlet API. Back in 2007, it was very cool to create Plexus components that were then automatically published as REST Resources in Nexus. But today, the same thing looks very cumbersome and is not what one would call a "state of the art". Back then, we had these goals in mind:

  • have complete REST API published on Nexus
  • have a decoupled UI application
  • provide XML/JSON serialized transport to REST Resource without any effort, with proper content negotiation (XML was kept as "Plan B")
  • make our REST Resources as Plexus components (to enjoy all the benefits of IoC, and later pluggability)

While we fulfilled much of these goals above, we did that at a high cost. For a Nexus core developer (or Nexus plugin developer), it is very cumbersome to create a new REST Resource using our classes, compared to what REST libraries are available today. Current state-of-the-art REST libraries make our initial implementation seem somewhat naive (hence the need to move toward new libraries like Enunciate). Our 1st and biggest mistake was a very deep class hierarchy in our current API. While all the "defaults" are properly configured, it is often difficult to create a non-trivial Resource in the current API if you are not intimately familiar with the system.

Also, in the initial design, we use XStream with a custom driver to produce JSON. Back then, it was a real pain to produce proper JSON out of Java. Today, we have libraries like Jackson. In the next interation of refactoring, you'll see update the infrastructure used to produce our REST services to bring it up to speed with what is available today.

The Benefits of "enunciating" a REST API

At first, we will use Enunciate with Nexus during build time only, to generate HTML documentation of our REST API. This documentation will be available publicly, but will also be bundled with every Nexus instance! Our work to modify our own REST infrastructure is going to require some "invasive" work, but I have to emphasize that Enunciate is not invasive if you use it on a modern JSR311 based REST applications. Enunciate is invasive for us only, since we are about to use it on a home grown, non-JSR311 REST application.

Enunciate gathers and builds your services model using your sources and all the metadata it finds (Java5 annotations, Javadoc). To "enunciate" the Nexus REST API, we had to add JSR311 annotations to our existing REST Resources. There was one more problem to solve: our method signatures are more "servlet like", and they didn't fit the model of a JSR311 REST Application. While a JSR311 application method signature completely describes the method expectations about payload, parameters, and response type, our methods – whether GET, PUT, POST or DELETE – have almost same signature: RestRequest, RestResponse, Variant. Hence, we had to add more metainformation describing what a method does: what it expects as input, if any, and what it sends out as response.

Luckily, it turned out that this was the only piece missing, and Enunciate was happy to generate documentation for us. Ryan added the new annotation that describes the "alternate REST Signature" of the method, and Enunciate got all the information it needed to generate documentation for us.

Another painful step yet to be completed is "freeing" our REST DTOs from Modello. Initially, we knew we wanted to version the DTOs used in REST. Hence, we used Modello to generate the DTOs. Later, problems with Modello and Restlet forced us to always use version 1.0 of our REST DTOs. Since Enunciate requires that DTOs have JAXB2 annotations, we decided to store our DTOs as code and ditch Modello in our builds.

All this looks like a lot of work, but it is actually pretty straightforward. While this might seem dull to someone not developing Nexus, this work is going to bring real value once it is completed. In addition to solving our documentation problems, Enunciate is going to open up a world of possibilities once we migrate our REST services over to the framework.

For more information about Enunciate, the Enunciate Wiki contains a nice example of how to use Enunciate in case like ours is, without JAX-RS. Example is shown here. Examples of Enunciate generated documentation can be seen on it's site. There is a great walk-through, with static examples.

Expect More Changes in the Next Few Months

As Nexus graduated from alphas, betas and now is at a 1.5.0 version, we realize we have to change gears to keep up. Enunciate is the 1st "newcomer" technology to Nexus stack. There will be more to come. Think of this as the Nexus 100,000 mile checkup. We're taking a look at the stack and taking this as an opportunity to upgrade where necessary.

One last note, this post is not about any deficiencies in Restlet. Restlet is a great framework, and it served us well. We – the Nexus Project team – are very thankful to Restlet.org project with all the help we got from them and for the great library they made.