I am struggling for a couple of days now with the following problem. I searched quite a lot for an answer, here in SO, in jersey mailing lists and the net in general, but weren't able to find answer to this particular question.
Setting up the problem domain...
I am using Jersey 1.16 inside Tomcat 7.
I have created a simple JAX-RS resource looking like this:
@Path("/")
@Produces({ "application/xml", "text/plain" })
public class ExampleResource {
@GET
public List<Thing> getThings() {
List<Thing> list = new ArrayList<>();
list.add(new Thing("a thing 1", "a thing description 1"));
list.add(new Thing("a thing 2", "a thing description 2"));
return list;
}
}
Thing
is a JAXB annotated POJO looking like this
@XmlRootElement(name = "thing")
public class Thing {
private String name;
private String description;
// getters, setters and @XmlElement annotations ommited for brevity
I have also configured WadlGeneratorJAXBGrammarGenerator.class
And when I ask for GET http://localhost:8092/rest
it works like a charm - nicely formatted collection of Thing
is returned.
The automatically generated WADL http://localhost:8092/rest/application.wadl
is almost perfect, it looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02">
<doc xmlns:jersey="http://jersey.java.net/" jersey:generatedBy="Jersey: 1.16 11/28/2012 02:09 PM" />
<grammars>
<include href="application.wadl/xsd0.xsd">
<doc title="Generated" xml:lang="en" />
</include>
</grammars>
<resources base="http://localhost:8092/rest/">
<resource path="/">
<method id="getThings" name="GET">
<response>
<ns2:representation xmlns:ns2="http://wadl.dev.java.net/2009/02"
xmlns="" element="thing" mediaType="application/xml" />
<representation mediaType="text/plain" />
</response>
</method>
</resource>
</resources>
</application>
Like I said, almost perfect, and therein lies the problem.
<ns2:representation xmlns:ns2="http://wadl.dev.java.net/2009/02"
xmlns="" element="thing" mediaType="application/xml" />
The WADL is not describing that /getThings
returns a List<Thing>
.
Rather, it looks like it is referring to a single element thing
in the xsd0.xsd
.
So, when I feed it in e.g. wadl2java, it generates untyped client.
In order to get a List<Thing>
I have to manually code it, something like
List<Thing> asXml = root().getAsXml(new GenericType<List<Thing>>(){});
Does anyone know if it is possible to have automatic WADL generation that would somehow indicate that this particular resource is returning a List of resources of a specific type?
And I don't want to create additional "ThingList" JAXB-annotated class and return that instead in my jersey resource.
I am almost there with generating the "perfect" WADL, it is just this (hopefully) little piece that I am missing...
Thank you very much!
I got the same problem and solved it by generating my own WADL.
For this you need to add the following files to your project
application-doc.xml for high level WADL overview comments
application-grammers.xml which defines the location of your schema ( with your Things and Thing elements and complextypes )
resourcedoc.xml , this is generated by a maven plugin and it reads your jersey classes, which contains your response element javadoc annotations.
just add this HrWadlGeneratorConfig class to your project and add this as init param to the jersey servlet
<init-param>
<param-name>com.sun.jersey.config.property.WadlGeneratorConfig</param-name>
<param-value>nl.amis.hr.wadl.HrWadlGeneratorConfig</param-value>
</init-param>
Class
package nl.amis.hr.wadl;
import com.sun.jersey.api.wadl.config.WadlGeneratorConfig;
import com.sun.jersey.api.wadl.config.WadlGeneratorDescription;
import com.sun.jersey.server.wadl.generators.WadlGeneratorApplicationDoc;
import com.sun.jersey.server.wadl.generators.WadlGeneratorGrammarsSupport;
import com.sun.jersey.server.wadl.generators.resourcedoc.WadlGeneratorResourceDocSupport;
import com.sun.research.ws.wadl.Grammars;
import com.sun.research.ws.wadl.Include;
import com.sun.research.ws.wadl.ObjectFactory;
import java.util.List;
public class HrWadlGeneratorConfig extends WadlGeneratorConfig {
@Override
public List<WadlGeneratorDescription> configure() {
ObjectFactory obj = new ObjectFactory() ;
Grammars gram = obj.createGrammars();
Include e = obj.createInclude();
e.setHref("schema.xsd");
gram.getInclude().add(e);
WadlGeneratorConfigDescriptionBuilder builder = generator(WadlGeneratorApplicationDoc.class)
.prop( "applicationDocsStream", "application-doc.xml" )
.generator( WadlGeneratorGrammarsSupport.class )
.prop( "grammarsStream", "application-grammars.xml" )
.generator( WadlGeneratorResourceDocSupport.class )
.prop( "resourceDocStream", "resourcedoc.xml" );
return builder.descriptions();
}
}
Here is a snippet of the Jersey class and the @response.representation.200.qname points to the element in your own schema.xsd
/**
* Returns the item if existing.
*
* @response.representation.200.qname employees
* @response.representation.200.mediaType application/xml,application/json
* @response.representation.200.doc This is the representation returned by default
* @response.representation.200.example {@link EmployeeExample#SAMPLE_ITEM}
*
*
* @return the requested item if this service is available
*/
@GET
public List<Employee> getEmployees() {
return hrBean.getEmployeesFindAll();
}
and the maven pom which generates the resourcedoc.xml which we be used by the WADL generator.
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.4</version>
</plugin>
</plugins>
</pluginManagement>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>javadoc</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
<configuration>
<encoding>UTF-8</encoding>
<verbose>false</verbose>
<show>public</show>
<subpackages>nl.amis.hr.restful</subpackages>
<doclet>com.sun.jersey.wadl.resourcedoc.ResourceDoclet</doclet>
<docletPath>${path.separator}${project.build.outputDirectory}</docletPath>
<docletArtifacts>
<docletArtifact>
<groupId>nl.amis.hr</groupId>
<artifactId>Model</artifactId>
<version>1.0-SNAPSHOT</version>
</docletArtifact>
<docletArtifact>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>wadl-resourcedoc-doclet</artifactId>
<version>1.17.1</version>
</docletArtifact>
<docletArtifact>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.17.1</version>
</docletArtifact>
<docletArtifact>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.6.1</version>
</docletArtifact>
</docletArtifacts>
<!-- the following option is required as a work around for
version 2.5 of the javadoc plugin which will be used
by a maven version > 2.0.9 -->
<useStandardDocletOptions>false</useStandardDocletOptions>
<additionalparam>-output ${project.build.outputDirectory}/resourcedoc.xml</additionalparam>
</configuration>
</plugin>
here is the full example on github https://github.com/biemond/JDeveloper12c_12.1.2/tree/master/RestFulOWSM/WebService