WADL generado para una lista de recursos
jaxb jersey (1)
Estoy luchando por un par de días con el siguiente problema. Busqué bastante por una respuesta, aquí en SO, en las listas de correo de jersey y en la red en general, pero no pude encontrar la respuesta a esta pregunta en particular.
Configurando el dominio del problema ...
Estoy usando Jersey 1.16 dentro de Tomcat 7.
Creé un recurso JAX-RS simple con el siguiente aspecto:
@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
es un POJO anotado JAXB que se parece a esto
@XmlRootElement(name = "thing")
public class Thing {
private String name;
private String description;
// getters, setters and @XmlElement annotations ommited for brevity
También he configurado WadlGeneratorJAXBGrammarGenerator.class
Y cuando solicito GET http://localhost:8092/rest
, funciona como un amuleto: se devuelve una colección de Thing
formato GET http://localhost:8092/rest
.
El WADL generado automáticamente http://localhost:8092/rest/application.wadl
es casi perfecto, se ve así:
<?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>
Como dije, casi perfecto, y ahí radica el problema.
<ns2:representation xmlns:ns2="http://wadl.dev.java.net/2009/02"
xmlns="" element="thing" mediaType="application/xml" />
El WADL no describe que /getThings
devuelve una List<Thing>
. Más bien, parece que se está refiriendo a un elemento thing
en el xsd0.xsd
. Entonces, cuando lo alimento en eg wadl2java, genera un cliente sin tipo. Para obtener una List<Thing>
tengo que codificarla manualmente, algo así como
List<Thing> asXml = root().getAsXml(new GenericType<List<Thing>>(){});
¿Alguien sabe si es posible tener una generación WADL automática que de alguna manera indique que este recurso particular está devolviendo una Lista de recursos de un tipo específico?
Y no quiero crear clases anotadas con JAXB "ThingList" adicionales y devolverlas en mi recurso jersey.
Ya casi estoy allí con la generación del WADL "perfecto", es solo esta (afortunadamente) pequeña pieza que me falta ...
¡Muchas gracias!
Obtuve el mismo problema y lo resolví generando mi propio WADL.
Para esto, necesita agregar los siguientes archivos a su proyecto
application-doc.xml para comentarios generales de WADL
application-grammers.xml que define la ubicación de su esquema (con sus elementos Things and Thing y complextypes)
resourcedoc.xml, esto es generado por un plugin maven y lee tus clases jersey, que contiene tus anotaciones javadoc del elemento de respuesta.
simplemente agregue esta clase HrWadlGeneratorConfig a su proyecto y agregue esto como init param al servlet jersey
<init-param>
<param-name>com.sun.jersey.config.property.WadlGeneratorConfig</param-name>
<param-value>nl.amis.hr.wadl.HrWadlGeneratorConfig</param-value>
</init-param>
Clase
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();
}
}
Aquí hay un fragmento de la clase Jersey y @ response.representation.200.qname apunta al elemento en su propio esquema.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();
}
y el maven pom que genera el resourcedoc.xml que será utilizado por el generador WADL.
<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>
aquí está el ejemplo completo en github https://github.com/biemond/JDeveloper12c_12.1.2/tree/master/RestFulOWSM/WebService