Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

 

 

 

Wiki Markup
{span:style=font-size:2em;font-weight:bold} JAX-RS Services Description {span}

 

 

 

Table of Contents

CXF JAX-RS supports (Web Application Description Language|http://www.w3.org/Submission/wadl] (WADL).
Users can use WADL documents to generate the initial code and have WADL auto-generated on demand.

...

A top level WADL document element is called "application". Usually it may contain a "grammars" section and "resources" element with one or more top-level "resource" elements, with each one representing a specific root resource, for example:

Code Block
xml
xml

<application xmlns="http://wadl.dev.java.net/2009/02" xmlns:ns="http://superbooks">
 <grammars>
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
        xmlns:tns="http://superbooks" attributeFormDefault="unqualified" elementFormDefault="unqualified" 
        targetNamespace="http://superbooks">
    <xs:element name="thebook" type="tns:book"/>
    <xs:complexType name="book">
        <xs:sequence>
            <xs:element minOccurs="0" ref="tns:thechapter"/>
            <xs:element name="id" type="xs:int"/>
        </xs:sequence>
    </xs:complexType>
  </xs:schema>
 </grammars>
 <resources base="http://localhost:8080/">
   <resource path="/bookstore/{id}">
     <param name="id" style="template"/>
     <method name="GET">
      <response>
       <representation mediaType="application/xml" element="ns:thebook"/>
      </response>
    </method>
   </resource>
   <resource path="/books">
      <resource path="/bookstore/{id}">
        <param name="id" style="template"/>
        <method name="GET">
          <response>
           <representation mediaType="application/xml" element="ns:thebook"/>
          </response>
        </method>
      </resource>
   </resource>
 </resources>  
</application>

...

Note that inlined schemas can be included instead by referencing external schemas. Likewise, most of WADL element declarations such as "resource", "method", "representation", etc can be shared by using the same document or external references. Here is how the basic example can be simplified with the help of references:

Code Block
xml
xml

<application xmlns="http://wadl.dev.java.net/2009/02" xmlns:ns="http://superbooks">
 <grammars>
   <include href="schemas/book.xsd"/>
 </grammars>

 <resource_type id="bookResource">
     <param name="id" style="template"/>
     <method name="GET">
       <response>
        <representation mediaType="application/xml" element="ns:thebook"/>
       </response>
    </method>
 </resource_type>

 <resources base="http://localhost:8080/">
   <resource path="/bookstore/{id}" type="#bookResource"/>
   <resource path="/books">
      <resource path="/bookstore/{id}" type="#bookResource"/>

   <!-- 
     or 
     <resource path="/books/bookstore/{id}" type="#bookResource"/>
   --> 
   </resource> 
 </resources>  
</application>

...

For example, the following baseApplication.wadl documents describes an abstract "bookResource" resource:

Code Block
xml
xml

<application xmlns="http://wadl.dev.java.net/2009/02" xmlns:ns="http://superbooks">
 <grammars>
   <include href="schemas/book.xsd"/>
 </grammars>

 <resource_type id="bookResource">
     <param name="id" style="template"/>
     <method name="GET">
       <response>
        <representation mediaType="application/xml" element="ns:thebook"/>
       </response>
    </method>
 </resource_type>
</application>

and this WADL document links to the abstract resource by using an external WADL reference with a "baseResource" fragment.

Code Block
xml
xml

<application xmlns="http://wadl.dev.java.net/2009/02" xmlns:ns="http://superbooks">
 
 <resources base="http://localhost:8080/">
   <resource path="/bookstore/{id}" type="baseApplication.wadl#bookResource"/>
   <resource path="/books">
      <resource path="/bookstore/{id}" type="baseApplication.wadl#bookResource"/>
   </resource> 
 </resources>  
</application>

...

Code generator expects WADL resource and method elements to have "id" attributes set which can provide hints on how to name generated classes and methods. For example:

Code Block
xml
xml

<application xmlns="http://wadl.dev.java.net/2009/02" xmlns:ns="http://superbooks">
 <grammars>
  <include href="schemas/book.xsd"/>
 </grammars>
 <resources base="http://localhost:8080/">
   <resource path="/bookstore/{id}" id="org.apache.cxf.jaxrs.systest.BookStore">
     <param name="id" style="template"/>
     <method name="GET" id="getBook">
      <response>
       <representation mediaType="application/xml" element="ns:thebook"/>
      </response>
    </method>
   </resource>
 </resources>  
</application>

...

Running wadltojava from the command line will produce:

No Format

wadl2java -p <package-name> -sp <[schema-namespace =]package-name>* 
          -tMap <schema-type = java-type>* -repMap <media-type = java-type>*
          -resource <resource-name> -b <binding-file-name>* -catalog <catalog-file-name> 
          -d <output-directory> -compile -classdir <compile-classes-directory> -interface -impl 
          -noTypes -inheritResourceParams -generateEnums -supportMultipleXmlReps -async<methodNames>*
          -xjc<xjc-arguments>* 
          -h -v -verbose -quiet <wadl>

...

At the moment it is possible to apply external JAXB customizations to WADL grammars however it is not possible yet to restrict a given customization to a specific WADL document or explicitly inlined schema. Linking binding to external schemas works, for example, the following bindings file can be used:

Code Block
xml
xml

<jaxb:bindings version="2.0"
	xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	schemaLocation="schemas/book.xsd"
	node="//xs:complexType[@name='book2']/xs:sequence/xs:element[@name='id']">
	<jaxb:property name="book2Id"/>
</jaxb:bindings>

...

If you need the code generated during Maven build then the following plugin can be used:

Code Block
xml
xml

<groupId>org.apache.cxf</groupId>
<artifactId>cxf-wadl2java-plugin</artifactId>
<version>2.4.1</version>

Add this plugin to the build section of your project's pom and specify a 'wadl2java' goal, for example:

Code Block
xml
xml

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-wadl2java-plugin</artifactId>
                <version>2.4.1</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <sourceRoot>${basedir}/target/generated/src/main/java</sourceRoot>
                            <wadlOptions>
                                <wadlOption>
                                    <wadl>${basedir}/src/test/resources/wadl/bookstoreImport.xml</wadl>
                                    <impl>true</impl>
                                    
                                    <packagename>org.apache.cxf.systest.jaxrs.codegen.service</packagename>
                                    <schemaPackagenames>
                                       <schemaPackagename>http://superbooks=org.apache.cxf.systest.jaxrs.codegen.schema</schemaPackagename>
                                    </schemaPackagenames>
                                    
                                </wadlOption>
                            </wadlOptions>
                        </configuration>
                        <goals>
                            <goal>wadl2java</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

...

CXF will generate artifacts in the <sourceRoot> directory. Configuration arguments which are included inside the <wadlOption> element are used to pass arguments to the tooling and correspond to the options outlined in the wadltojava section, they can be specified explicitly, as above, or using an "extraargs" wrapper, for example:

Code Block
xml
xml

<wadlOptions>
	<wadlOption>
		<wadl>$\{basedir}/src/main/wadl/bookStore.wadl</wsdl>
                <extraargs>
                    <extraarg>-impl</extraarg>
                    <extraarg>-verbose</extraarg>
                </extraargs>
	</wadlOption>
</wadlOptions>

...

Another approach is to use org.apache.cxf.tools.wadlto.jaxrs.JAXRSContainer class shipped with the cxf-tools-wadlto-jaxrs module:

Code Block
xml
xml

<groupId>org.apache.cxf</groupId>
<artifactId>cxf-tools-wadlto-jaxrs</artifactId>
<version>2.4.1</version>

...

External WADL documents can be linked to from jaxrs:server endpoints using newly introduced "docLocation" attribute, for example:

Code Block
xml
xml

<jaxrs:server address="/rest" docLocation="wadl/bookStore.wadl">
   <jaxrs:serviceBeans>
      <bean class="org.bar.generated.BookStore"/> 
   </jaxrs:serviceBeans>
</jaxrs:server>

If external WADL documents include external schemas and jaxrs endpoints need to have the schema validation enabled, then those schemas can be referenced in the jaxrs:schemaLocations section as well.

WADL Auto Generation at Runtime

Note that in CXF 3.0.0 WADL Generator code has been moved to

Code Block
xml
xml

<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-rs-service-description</artifactId>
  <version>3.0.0-milestone1</version>
</dependency>

...

Note that starting from CXF 2.4.0, Description annotations can be applied to input parameters. Additionally, a method-level Descriptions annotation can have a collection of categorized Description annotations, with each Description targeting a specific WADL element by setting its 'target' property to one of the DocTarget values. For example, one can use a Descriptions annotation to document the response representation of a particular resource method, as well as add documentation fragments to WADL wadl:method/wadl:request and wadl:method/wadl:response elements:

Code Block
java
java

@POST
@Path("books/{bookid}")
@Descriptions({ 
   @Description(value = "Adds a new book", target = DocTarget.METHOD),
   @Description(value = "Requested Book", target = DocTarget.RETURN),
   @Description(value = "Request", target = DocTarget.REQUEST),
   @Description(value = "Response", target = DocTarget.RESPONSE),
   @Description(value = "Resource", target = DocTarget.RESOURCE)
})
public Book addBook(@Description("book id") @PathParam("id") Long id, @Description("New Book") Book book) {...}

Every unique @Path value adds a new 'resource' element to the generated WADL, thus the last Description annotation in the @Descriptions array ensures the doc extension is also added to the 'resource' element. Note that multiple resource methods having different HTTP methods but sharing the same @Path value will have the same parent 'resource' element representing this shared path fragment, in this case a Description with the DocTarget.RESOURCE target will be ignored unless it is added to the first resource method with this shared @Path:

Code Block
java
java

@POST
@Path("books/{bookid}")
@Description(value = "Resource", target = DocTarget.RESOURCE),
public Book addBook(@Description("book id") @PathParam("id") Long id, @Description("New Book") Book book) {...}

@GET
@Path("books/{bookid}")
public Book addBook(@Description("book id") @PathParam("id") Long id) {...}

Customizing WADL Generation

Support for Javadoc

In CXF 3.0.0 one can get the Javadoc documentation copied to WADL being auto-generated at runtime.One can register a custom WadlGenerator as a jaxrs:provider. The custom generator can extend the default

org.apache.cxf.jaxrs.model.wadl.WadlGenerator or register a default one with one of the following properties set.JavaDocProvider implements org.apache.cxf.jaxrs.model.wadl.DocumentationProvider and can be set as WADLGenerator "documentationProvider" property.

JavaDocProvider can be customized with URL or relative String path pointing to the generated Javadoc jar, so this jar can be shipped in the application war or located elsewhere.

JavaDocProvider parses the generated Javadoc HTML pages and scrapes the documentation. See Java to Wadl section on the alternative approach for supporting Javadoc.

Customizing WADL Generation

One can register a custom WadlGenerator as a jaxrs:provider. The custom generator can extend the default
org.apache.cxf.jaxrs.model.wadl.WadlGenerator or register a default one with one of the following properties set.

  • wadlNamespace: default is "http://wadl.dev.java.net/2009/02", the earlier one is "http://research.sun.com/wadl/2006/10".
  • singleResourceMultipleMethods: default is 'true', for example, if a resource class has multiple methods supported at the same path such as "/" (GET, POST, etc) then WADL will list them all as the child nodes of a single resource element.
  • useSingleSlashResource: default is false, for example, if you have a root resource class with a path "root" and a resource method with a path "" or "/" then a
  • wadlNamespace: default is "http://wadl.dev.java.net/2009/02", the earlier one is "http://research.sun.com/wadl/2006/10".
  • singleResourceMultipleMethods: default is 'true', for example, if a resource class has multiple methods supported at the same path such as "/" (GET, POST, etc) then WADL will list them all as the child nodes of a single resource element.
  • useSingleSlashResource: default is false, for example, if you have a root resource class with a path "root" and a resource method with a path "" or "/" then a WADL resource representing the root will not have a child resource representing this resource method (it would do if a resource method had a more specific path such as "bar").

...

Starting from CXF 2.5.5 and 2.6.2 it is possible to get explicit collections represented in generated WADL grammar sections and have WADL representations linking to these schema elements. Note it is only possible for JAXB collections, for example:

Code Block
java
java


@GET
@Path("books")
@org.apache.cxf.jaxrs.model.wadl.XMLName("{http://books}books")
public List<Book> getBooks() {...}

...

Even when you do use JAXB, the JAXB types may have been generated from the external schema so having WadlGenerator attempting to recreate the original schema may not work well. To have a generated WADL referencing the original schema(s) please set a 'schemaLocations' list property (programmatically or from Spring) :

Code Block
java
java

WadlGenerator wg = new WadlGenerator();
wg.setSchemaLocations(Collections.singletonList("classpath:/book.xsd"));

...

Note that the root schema such as "book.xsd" is inlined - you can have it referenced only by setting an 'externalLinks' list property. This will work very well when the "book.xsd" is indeed available at the external URI, but this property can also be used to avoid the local schemas being inlined. Moreover, the use of JAXB will not be required. The result will look like this:

Code Block
xml
xml

<wadl:grammars>
<wadl:include href="http://books.xsd"/>
</wadl:grammars>

...

You can also customize the way schema elements are referenced. When WadlGenerator creates WADL representation elements (representing resource method input or output types) it will be able to link to schema elements provided a given type is actually a JAXB one, so the result may look like this :

...


<!-- 
  thebook2 element is declared in a schema inlined in or referenced from the grammar section
  prefix1 is bound to that schema's target namespace and is declared at the wadl:application element 
-->
<representation mediaType="application/xml" element="prefix1:thebook2"/>

so the result may look like this :

Code Block
xml
xml
<!-- 
  thebook2 element is declared in a schema inlined in or referenced from the grammar section
  prefix1 is bound to that schema's target namespace and is declared at the wadl:application element 
-->
<representation mediaType="application/xml" element="prefix1:thebook2"/>

If no JAXB is used then you can attach an XMLName annotation to method input or output types. Alternatively, you can register an instance of ElementQNameResolver with the WadlGenerator which will be used for creating wadl:representation/@element values.

Changing the base address

Starting from CXF 2.6.2 it is possible to affect the base address specified in the auto-generated WADL (in wadl:resources/@base attribute).
WADLGenerator can be indirectly configured by setting a jaxrs:server/@publishedEndpointUrl attribute, similarly to the way CXF WSDL generator can be configured by setting a jaxws:endpoint/@publishedEndpointUrl attribute.

java2wadl Maven plugin

CXF 3.0.0 and 2.7.11 introduce java2wadl plugin for generating WADL at the build time:

Code Block
xml
xml
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-java2wadl-plugin</artifactId>
<version>3.0.0</version>

Add this plugin to the build section of your project's pom, for example:

Code Block
xml
xml
<build>
     <plugins>
            
       <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-java2wadl-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <!-- Enable if support for Javadoc is required -->
                    <!--
                    <execution>
                        <id>parsejavadoc</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>parsejavadoc</goal>
                        </goals>
                    </execution>
                    -->
                    <execution>
                        <id>process-classes</id>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>java2wadl</goal>
                        </goals>
                        <configuration>
                            <classResourceNames>
                                    <classResourceName>a.b.c.CustomerService</classResourceName>
                            </classResourceNames>
                            <!-- Enable if support for Javadoc is required -->
                            <!--
                            <docProvider>org.apache.cxf.maven_plugin.javatowadl.ResourceMapJavaDocProvider</docProvider>
                            -->
                            <attachWadl>true</attachWadl>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Note that Javadoc can be properly supported by enabling the "parsejavadoc" execution and a docProvider property

If no JAXB is used then you can attach an XMLName annotation to method input or output types. Alternatively, you can register an instance of ElementQNameResolver with the WadlGenerator which will be used for creating wadl:representation/@element values.

Changing the base address

Starting from CXF 2.6.2 it is possible to affect the base address specified in the auto-generated WADL (in wadl:resources/@base attribute).
WADLGenerator can be indirectly configured by setting a jaxrs:server/@publishedEndpointUrl attribute, similarly to the way CXF WSDL generator can be configured by setting a jaxws:endpoint/@publishedEndpointUrl attribute.

Service listings and WADL queries

...

For example, given

Code Block
xml
xml

Base address : 'http://localhost:8080'
WAR name : 'store'
CXFServlet : '/books/*'
jaxrs:server/@address = '/orders'

...

For example, if the following 2 root resource classes has been registered with this endpoint:

Code Block
java
java

@Path("/fiction") 
public class FictionBookOrders {
}
@Path("/sport") 
public class SportBookOrders {
}

...