Search This Blog

Friday, September 9, 2011

Documenting Web Services with Enunciate


Understanding the workings of a Web Service from the perspective of a consumer, be it REST or SOAP based is not the easiest. Wading through a WADL or a WSDL is not a fun task, at least not for me.  Been looking into an open source project that has been around for some time called Enunciate and am pretty impressed by its capabilities.

Enunciate provides automated documentation of your resources and end points. It also has the ability to generate client artifacts for consuming the JAX-RS services in many different programming languages.

The process is itself quite simple. After creating your web service you have enunciate run as part of your build process and it generates nice HTML based documentation of your service along with client code (Yeah!) in different languages to consume the service. Using annotation based web services facilitates this nice magic I guess.

To experience enunciate for myself, I created a simple web service that exposes SOAP and REST based calls of the same underlying API.

A few simple criteria that I had for my sample application:
  • Documentation should be available at the Root context
  • Resources and Services must also be available at the Root context
To my pom, I added the necessary enunciate dependencies as shown below:
                                       
<dependencies>
  .... 
   <dependency>
        <groupId>org.codehaus.enunciate</groupId>
        <artifactId>enunciate-rt</artifactId>
	<version>1.24</version>
   </dependency>
 </dependencies>

<build>
  <plugins>
    ...
    <plugin>
          <groupId>org.codehaus.enunciate</groupId>
        <artifactId>maven-enunciate-plugin</artifactId>
        <version>1.24</version>
        <configuration>
          <configFile>enunciate.xml</configFile>
        </configuration>
        <executions>
           <execution>
              <goals>
                 <goal>assemble</goal>
              </goals>
          </execution>
        </execution>
    </plugin>
 </plugins>
To customize where my service's resources will be available, i.e., at the ROOT context I created an enunciate.xml file:
<enunciate xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://enunciate.codehaus.org/schemas/enunciate-1.21.xsd">
  
	<services>
		<<est defaultRestSubcontext="/"/>
		<soap defaultSoapSubcontext="/"/>
	</services>

	<modules>
		<spring-app disabled="true" />
		<docs docsDir="/" splashPackage="com.welflex.rest" title="Greetings Web Service API"
			copyright="Welflex"/>
	</modules>
</enunciate>
After building and running the web service, a nicely generated introduction page that looks like:


Navigating the application, one can view the Greeting Resource and Greeting Web Service end point documentation:




















Generated libraries for consuming the service are available for download as well along with documentation on how to use them, pretty sweet huh?


A maven example demonstrating the above is available for DOWNLOAD HERE

Once you download the example, execute:
>mvn install
>mvn jetty:run-exploded

Access the service at http://localhost:8080

Note that executing mvn jetty:run would give me a 404's. My only option was the  run-exploded. Enuciate creates an altered web.xml with its own custom classes. I am also curious to know whether using enunciate impacts the performance of the web service, and if so, by how much. Enunciate also facilitates skinning the documentation, I have not done the same but from their documentation it looks pretty straight forward.

I found that if one has a custom Servlet Filter and/or Listener defined in the project's web.xml then to get the same included into the final web.xml generated by enunciate, one would need to set the following in enunciate.xml.
<webapp mergeWebXML="src/main/webapp/WEB-INF/web.xml" />
Upon merging the same, my application started throwing 404's when attempting to access the documentation. In other words, using a custom servlet filter or listener with my use case of resources mounted at root context does not seem to work with my application and needs further investigation.Without being able to set Custom Filters and Listeners is a major blocker.

Another tool that I have included in the pom is JAX-Doclets which generate nice javadoc for the JAX-RS portion of the service. To view the same execute mvn site and navigate to the generated documentation.