Documentar APIs REST con Enunciate

Enunciate es una herramienta de documentación de servicios que se integra en nuestro proyecto y permite documentar automáticamente nuestra API REST en formato HTML.

Enunciate se invoca desde proyectos FundeWeb mediante la ejecución de una tarea ANT creada para tal efecto (similar a la invocación de Genética). Además de ANT, Enunciate se puede integrar mediante Maven, Gradle o directamente por programación.

La configuración de Enunciate se basa en el fichero enunciate.xml. En este fichero se puede configurar tanto aspectos visuales de la documentación (textos, estilos, plantillas, etc.) como funcionales (módulos, namespaces, rutas, etc.). Desde MNCS proporcionamos un archivo enunciate.xml con la configuración básica, así como la plantilla traducida y la hoja de estilo modificada para generar el HTML con un aspecto similar a las aplicaciones FundeWeb.

Para generar una documentación completa, Enunciate extrae información del Javadoc de las clases del servicio. Además, proporciona una serie de anotaciones que completan el conjunto de conceptos usados en los servicios REST (códigos de respuesta, códigos de alerta, cabeceras, parámetros, ejemplos de peticiones, etc.). Una vez configurado Enunciate, se recomienda revisar la sección de Anotaciones para ampliar los comentarios de los servicios a documentar.

Instalación y configuración de Enunciate mediante tareas Ant para aplicaciones FundeWeb 2 desplegadas en WebLogic 12.1.3 (IDE FundWeb 2.0).

Instalación

Enunciate vendrá incorporado en la versión de FundeWeb 2.0.42 y posteriores. Por lo que no será necesario realizar algunos de los pasos.

  1. Descargar Enunciate desde el siguiente enlace. Ignorar paso si estas en FundeWeb 2.0.42 o posterior.
  2. Descomprimir el archivo descargado en el paso 1 la carpeta de utilidades de la instalación de FundeWeb (por defecto: C:\FundeWeb\2.0\utilidades). Ignorar paso si estas en FundeWeb 2.0.42 o posterior.
  3. Renombrar la carpeta generada, para que quede con el nombre enunciate. Ignorar paso si estas en FundeWeb 2.0.42 o posterior.
  4. Descargar los archivos de configuración de Enunciate-FundeWeb: enunciate-fdw. Ignorar paso si la aplicación esta creada con el arquetipo de FundeWeb 2.0 versión 0.0.11 o posterior.
  5. Descomprimir el archivo descargado en el paso 3 en la carpeta raíz del proyecto a documentar (por ejemplo: C:\FundeWeb\2.0\workspace\portalfundeweb). Ignorar paso si la aplicación esta creada con el arquetipo de FundeWeb 2.0 versión 0.0.11 o posterior.
  6. Desde Eclipse → Window → Preferences , crear la propiedad Ant fundeweb.enunciate.home apuntando a la carpeta de la instalación de Enunciate descargada en el paso 2.. Ignorar paso si la aplicación esta creada con el arquetipo de FundeWeb 2.0 versión 0.0.11 o posterior.
  7. Copiar en el fichero build.xml la tarea ant para lanzar Enunciate: ( Ignorar paso si la aplicación esta creada con el arquetipo de FundeWeb 2.0 versión 0.0.11 o posterior.)
	<!-- Tareas para ENUNCIATE -->
	<target name="enunciate.generate.doc" description="Generador documentacion REST">
		<timestamp message="Inicio de generacion de documentacion de Enunciate"/>
 
		<delete dir="${basedir}/generacion/enunciate/build" failonerror="no"/>
		<mkdir dir="${basedir}/generacion/enunciate/build" />
 
		<path id="enunciate.classpath">
			<fileset dir="${fundeweb.enunciate.home}/lib">
				<include name="*.jar" />
			</fileset>
		</path>
 
		<taskdef name="enunciate" classname="com.webcohesion.enunciate.EnunciateTask">
			<classpath refid="enunciate.classpath" />
		</taskdef>
 
		<enunciate basedir="${basedir}${enunciate.package.rest}"
					configFile="${basedir}/generacion/enunciate/resources/enunciate.xml" compiledebuginfo="true"
					buildDir="${basedir}/generacion/enunciate/build">
			<include name="**/*.java" />
			<classpath refid="enunciate.classpath" />
		</enunciate>
 
                <copy todir="${basedir}/generacion/enunciate/build/docs/img" overwrite="true">
	    	       <fileset dir="${basedir}/generacion/enunciate/resources/img" />
                </copy>
 
		<timestamp message="Fin de generacion de documentacion. Comenzando la copia de ficheros."/>
 
		<antelope:if>
				<bool>
					<isset property="enunciate.web.doc.path" />
				</bool>
			<echo message="Copiando documentacion a la carpeta: ${basedir}/${enunciate.web.doc.path}" />
			<copy todir="${basedir}\${enunciate.web.doc.path}" overwrite="true">
				<fileset dir="${basedir}/generacion/enunciate/build/docs" />
			</copy>
		</antelope:if>
		<timestamp message="Fin generate.doc"/>
	</target>
	<!--  -->

Configuración

Ignorar paso si la aplicación esta creada con el arquetipo de FundeWeb 2.0 versión 0.0.11 o posterior.

Una vez instalado Enunciate y creada la tarea Ant en el build.xml, hay que crear las siguientes propiedades en el fichero build.properties para configurar la información específica de nuestro proyecto:

## Variables para ejecución de ENUNCIATE (GENERACION DE DOCUMENTACIÓN REST)
enunciate.package.rest=/web/src/main/java/unica/rest/servicios/
#comentar para no pasar doc al módulo web
enunciate.web.doc.path=\\web\\src\\main\\web_resources\\doc\\
 
## Variables de configuración de ENUNCIATE
enunciate.api.version=v1
enunciate.api.title=UNICA API REST
enunciate.api.header=Documentación API REST UNICA
enunciate.api.description=Esta es la documentación de la API REST de la aplicación UNICA, para más información escriba a: mcns@um.es
enunciate.private.package=unica.rest.servicios.auth
enunciate.rest.root=../services/rest/

Los parámetros para configurar Enunciate son:

  • enunciate.package.rest: Ruta del paquete de las fuentes que contiene los servicios.
  • enunciate.web.doc.path: Carpeta del módulo web donde se copiará la documentación para ser publicada (si se comenta no se publica)
  • enunciate.api.version: Versión del API.
  • enunciate.api.title: Nombre de la aplicación, texto que aparece en la cabecera del template.
  • enunciate.api.header: Texto encabezado en la documentación HTML.
  • enunciate.api.description: Texto de descripción en la documentación HTML (debajo de enunciate.api.header).
  • enunciate.private.package: Paquete privado para el que no se generará documentación ni se publicará.
  • enunciate.rest.root: Ruta de publicación de los servicios.

Instalación y configuración de Enunciate mediante plugin Maven para aplicaciones FundeWeb 2 desplegadas en WebLogic 12.2 (IDE FundWeb 2.1).

Instalación

1. Añadir las siguientes properties en el pom.xml del módulo web.

        <properties>
        ..
        <enunciate.resources>${maven.multiModuleProjectDirectory}\..\generacion\enunciate\resources\</enunciate.resources>
        <enunciate.build.directory>${maven.multiModuleProjectDirectory}\..\generacion\enunciate\build\</enunciate.build.directory>      
        ..
        </properties>

2. En el mismo fichero pom.xml, añadir el siguiente plugin dentro del primer bloque build:

   <build>
	<finalName>[APLICACION]-web</finalName>
	<plugins>
             ...
             <plugin>
		<groupId>com.webcohesion.enunciate</groupId>
		<artifactId>enunciate-maven-plugin</artifactId>
		<version>2.12.1</version>
		<configuration>
		<configFile>${enunciate.resources}\enunciate.xml</configFile>
                    <!-- Ejemplo inclusión/exclusión como sources de artefactos externos -->
                    <!--
                    <sourcepathIncludes>
                    	<sourcepathInclude>
                        	<groupId>es.um.atica.fundeweb</groupId>
                        	<artifactId>fundeweb-jaxrs</artifactId>
						</sourcepathInclude>
                        <sourcepathInclude>
                        	<groupId>es.um.atica.fundeweb.weblogic</groupId>
							<artifactId>fundeweb-java-services-config</artifactId>
						</sourcepathInclude>
						<sourcepathInclude>
                        	<groupId>es.um.atica.fundeweb.weblogic</groupId>
                            <artifactId>fundeweb-jersey</artifactId>
                        </sourcepathInclude>
                    </sourcepathIncludes>
                    <sourcepathExcludes >
						<sourcepathExclude>
                        	<groupId>javax.ws.rs.</groupId>
                            <artifactId>jsr311-api</artifactId>
						</sourcepathExclude>
						<sourcepathExclude>
                        	<groupId>javax.ws.rs.</groupId>
                            <artifactId>javax.ws.rs-api</artifactId>
						</sourcepathExclude>
                    </sourcepathExcludes>
                    -->
                </configuration>           
                <executions>
                    <execution>
                        <goals>
                            <goal>docs</goal>
                        </goals>
                        <configuration>
                            <skipEnunciate>true</skipEnunciate>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
...
   </plugins>

3. Descargar los ficheros de configuración y descomprimirlos en “generacion/enunciate/”.

4. Copiar en el fichero build.xml la tarea ant para lanzar el plugin de Enunciate:

 <!-- Tareas para ENUNCIATE -->
    <target name="enunciate.generate.doc" description="Generador documentacion REST - FundeWeb 2.1" depends="init">
        <timestamp message="Inicio de generacion de documentacion de Enunciate"/>
 
        <timestamp message="Limpieza de generación anterior." />
        <delete dir="${basedir}/generacion/enunciate/build" failonerror="no"/>
        <mkdir dir="${basedir}/generacion/enunciate/build" />
 
        <timestamp message="Inicio install módulo WEB." />
        <echo message="Instalando el módulo WEB (mvn install). Log en el fichero: maven_web_install.log." />
        <maven module="web" task="install" description="Instalar el proyecto (mvn install)." log.file="maven_web_install.log" />
        <timestamp message="Fin install." />
 
        <timestamp message="Invocación plugin maven ENUNCIATE. Log en el fichero: maven_enunciate_docs.log." />
        <maven module="web" task="enunciate:docs" description="Pasando Enunciate (mvn -e enunciate:docs)." log.file="maven_enunciate_docs.log" />
        <timestamp message="Fin de generacion de documentacion. Comenzando la copia de ficheros."/>
 
        <copy todir="${basedir}/generacion/enunciate/build/docs/img" overwrite="true">
                       <fileset dir="${basedir}/generacion/enunciate/resources/img" />
        </copy>
 
        <timestamp message="Borrando targets"/>
        <delete dir="${web.target.dir}/${web.module.name}" failonerror="true" />
        <delete dir="${web.target.dir}/maven-status" failonerror="true" />
        <delete dir="${web.target.dir}/enunciate" failonerror="true" />
        <delete failonerror="true">
            <fileset dir="${web.target.dir}">
                <include name="${web.module.name}*.jar" />
                <include name="${web.module.name}*.war" />
                <exclude name="generated-sources" />
                <exclude name="m2e-wtp" />
                <exclude name="classes" />
            </fileset>
        </delete>
        <timestamp message="Targets borrados"/>
 
	<antelope:if>
		<bool>
			<isset property="enunciate.web.doc.path" />
		</bool>
		<echo message="Copiando documentacion a la carpeta: ${basedir}/${enunciate.web.doc.path}" />
			<copy todir="${basedir}\${enunciate.web.doc.path}" overwrite="true">
				<fileset dir="${basedir}/generacion/enunciate/build/docs" />
			</copy>
	</antelope:if>
	<timestamp message="Fin generate.doc"/>
   </target>
<!--  -->

Configuración

Una vez añadido el plugin y creada la tarea Ant en el build.xml, hay que crear la siguiente propiedad en el fichero build.properties para determinar si la documentación generada se pasa al módulo web de nuestro proyecto y se publica junto al resto de páginas.

## Variables para ejecución de ENUNCIATE (GENERACION DE DOCUMENTACIÓN REST)
#comentar para no pasar doc al módulo web
enunciate.web.doc.path=\\web\\src\\main\\web_resources\\doc\\

El resto de configuración se realiza en el fichero enunciate.xml.

En este fichero se especifica el título y la descripción que aparecerá en la documentación HTML, así como los paquetes a analizar buscando servicios a documentar y los módulos de Enunciate a generar.

Sustituye todos los textos entre corchetes por la información propia de tu aplicación.

Puede ampliarse más información en la WiKi de Enunciate.

Una vez realizados los pasos anteriores dispondremos de la configuración básica para invocar Enunciate y generar la documentación de nuestra API REST. Para ello necesitamos ejecutar la tarea Ant enunciate.generate.doc (1) creada anteriormente.

En la imagen puede observarse que, con las rutas por defecto, la documentación generada se ubica en la carpeta /generacion/enunciate (2).

Además, si se ha establecido la variable enunciate.web.doc.path en el fichero build.properties, la carpeta /docs se copiará al módulo web de nuestro proyecto quedando así publicada junto al resto de la aplicación (3).

Para aplicaciones desplegadas en el IDE de FundeWeb 2.1, además, se crearán dos ficheros en la carpeta log/ con el resultado del install del módulo web y de la ejecución del plugin de Maven.

Guía de Enunciate

Toda la configuración de Enunciate se realiza a través del fichero enunciate.xml. Este fichero se copia a la raíz del proyecto al descomprimir el fichero .7z del apartado de instalación y establece la configuración básica proporcionada por MNCS.

En este fichero se establecen los textos que aparecen en el HTML, algunos metadatos de nuestra API, la posible exclusión de clases, definición de namespaces y los distintos módulos que se van a generar.

El concepto de módulo es básico en Enunciate. Un módulo es una extensión por la que se indica a Enunciate que debe generar los archivos para una determinada tecnología (jaxb, jaxws, php, ruby…).

Por defecto se genera la documentación para todos los módulos.

Para desactivar un módulo hay que indicarlo explícitamente añadiendo el módulo y poniendo disabled=“true”.

A continuación se detallan los aspectos más importantes de la configuración del fichero enunciate.xml.

Puede obtenerse más información en la wiki de Enunciate User Guide.

Facets

Se pueden crear facets para agrupar acciones sobre determinados paquetes. Con la configuración básica proporcionada se ha creado un facet “private” para no generar documentación sobre determinados paquetes privados que se deseen omitir.

Puede obtenerse más información en las wikis de Enunciate Facets y Excluding Including Classes.

Estilos

Por defecto Enunciate genera la documentación en base a una hoja de estilo y a una plantilla de transformación propia contenidas en sus librerías. La ejecución de Enunciate permite parametrizar estos aspectos visuales, así que desde MNCS hemos realizado algunas modificaciones en los ficheros “visuales” para dar un aspecto más corporativo. Estos ficheros se copian al proyecto al descomprimir los archivos .7z del apartado de instalación.

  • enunciate.css: hoja de estilo modificada.
  • enunciate.fmt: plantilla freemarker usada para la generación del html a partir de los objetos java de enunciate.

Puede obtenerse más información en la wiki de enunciate Custom Skin.

Módulos

Como se ha mencionado anteriormente, un módulo es una extensión de Enunciate que especifica la tecnología para la cuál se generará la documentación (y los objetos, según el caso).

Por defecto todos los módulos se generan automáticamente. Para especificar que no se desea generar un módulo, hay que incluirlo específicamente con el atributo disabled=“true”.

A continuación se mencionan los módulos más relevantes de Enunciate:

  • docs: Módulo principal para generar la documentación. En este módulo se configura la hoja de estilo y la plantilla a usar en la generación, así como las rutas donde se colocará el resultado.
  • jaxrs: Módulo para indicar el procesamiento de los servicios REST.
  • jackson: Módulo para analizar las clases usadas en la API REST que pueden ser (de)serializadas usando Jackson2.
  • jaxb: Módulo para analizar las clases usadas en la API REST que pueden ser (de)serilizadas usando JAXB.
  • java-json-client: Módulo para crear los ficheros con el modelo de datos Jackson a usar por los clientes.
  • java-xml-client Módulo para crear los ficheros con el modelo de datos JAXB a usar por los clientes.

Puede obtenerse más información sobre el resto de módulos en la wiki de Enunciate Modules.

Anotaciones

Para generar una documentación HTML lo más completa posible es necesario completar el Javadoc de nuestros servicios.

Es aconsejable comentar la declaración de las clases de nuestros servicios. De esta forma aparecerá en la descripción del recurso en la documentación HTML.

Además, Enunciate proporciona una serie de etiquetas para ayudar a completar la documentación. Estas son algunas de las más interesantes:

  • @HTTP: Usada para documentar los diferentes códigos de respuesta HTTP que pueden devolver un método. A nivel de clase o de método.
  • @HTTPWarning : Usada para especificar situaciones de alerta en la lógica del recurso. A nivel de clase o método.
  • @returnWrapped: Usada para ayudar a Enunciate a encontrar la clase devuelta en un recurso. A nivel de método.
  • @inputWrapped: Usada para ayudar a Enunciate a encontrar la clase enviada a un recurso. A nivel de método.
  • @RequestHeader: Usada para especificar un parámetro pasado por la cabecera HTTP a un método.A nivel de clase o método. !OJO! sí la cabecera se manda como un @HeaderParam, NO SE DEBE USAR ESTA anotación. Mantener solo la anotación @param de Javadoc.
  • @ResponseHeader: Usada para especificar una variable incluida en la cabecera HTTP de la respuesta. A nivel de clase o método.
  • @requestExample: Usada para documentar un ejemplo de petición (JSON o XML). A nivel de método. Requiere añadir el mediaType.
  • @responseExample: Usada para documentar un ejemplo de respuesta (JSON o XML). A nivel de método. Requiere añadir el mediaType.
  • @pathExample: Usada para documentar un ejemplo de llamada al servicio. A nivel de método.
  • @ignore: Usada para ignorar una clase o un método y que no se genere su documentación. A nivel de clase o método.

Puede obtenerse más información sobre las anotaciones en la Wiki de Enunciate Enunciate Specific Annotations.

Todos los ejemplos mostrados usan etiquetas Javadoc para generar la documentación.

En aplicaciones desplegadas en WebLogic 12.2, si se desea ampliar el mecanismo y usar las anotaciones propias de Enunciate que figuran en su WiKi habrá que añadir la siguiente dependencia a los pom.xml de la aplicación:

<dependency>
    <groupId>com.webcohesion.enunciate</groupId>
    <artifactId>enunciate-core-annotations</artifactId>
    <version>2.12.1</version>
</dependency>

Otros Recursos

También debemos asegurarnos que nuestro proyecto tiene los “build files” acordes:

build.xml v0.0.12 Este fichero ya contiene la tarea ANT configrada en los pasos anteriores. Incluido en el arquetipo de FundeWeb 2.0 versión 0.0.11 o posterior.

common.build.xml v0.0.13. Incluido en el arquetipo de FundeWeb 2.0 versión 0.0.11 o posterior.

Pon aquí tus propuestas de FAQs, indicando qué problema tienes, y buscaremos la solución lo antes posible. Si además lo has resuelto, puedes indicar cómo lo has hecho.

Formato de petición de FAQ:

**Título**
//Descripción del problema//
//Tecnología afectada (Fundeweb 1/2)//
//Cómo reproducir el error//
**Solución**
//Descripción de la solución//

Tus datos de contacto  --- //[[correo@umOticarum.es|Tu Nombre]] dd/mm/yyyy //


FAQs Resueltas

Problema al encontrar clases

Si nuestro servicio hace uso de clases/librerías que no están en la ruta definida en la variable enunciate.package.rest, Enunciate dará un error generando la documentación.

Solución

La solución pasa por modificar la tarea ANT en el build.xml y añadir classpath's con las rutas donde se encuentran las clases/librerías.
Esto también sirve para añadir librerías del repositorio maven local.
También es posible añadir las fuentes de las librerías como sourcepath para que genere la documentación de clases aunque no estén en nuestro proyecto.

Ejemplo:
Para generar la documentación cuando se están usando las clases del manejo de errores de la WiKi Manejo de errores en servicios REST, es necesario definir los path de la tarea ANT enunciate.generate.doc de la siguiente forma:

 <!-- librerias enunciate -->
<path id="enunciate.classpath">
	<fileset dir="${fundeweb.enunciate.home}/lib">
		<include name="*.jar" />
	</fileset>
</path>
 
<!-- librerias incluidas con maven -->
<!-- hay un problema con el rango de las versiones, lo ideal seria incluir todas asi-->
<artifact:dependencies pathId="dependency.rest.classpath" >
	<artifact:localRepository path="${fundeweb.maven.repository}" />
	<dependency groupId="org.um.atica" artifactId="ejb_interfaces" version="[2.0.0, 2.1.0)" scope="compile" />
	<dependency groupId="com.sun.jersey" artifactId="jersey-core" version="1.19.4" scope="compile" />
</artifact:dependencies>
 
<!-- librerias propias incluidas manualmente -->
<!-- no se pueden incluir con artifact:dependencies por fallo con rango de versiones -->
<path id="fundeweb.rest.classpath">
	<fileset dir="${fundeweb.maven.repository}/es/um/atica/fundeweb">
		<include name="**/*.jar"/>
		<exclude name="**/*-sources.jar"/>
	</fileset>
 
	<fileset dir="${fundeweb.maven.repository}/org/hibernate">
		<include name="**/*.jar" />
		<exclude name="**/*-sources.jar"/>
	</fileset>
 
	<fileset dir="${fundeweb.maven.repository}/org/jboss/seam/jboss-seam">
		<include name="**/*.jar" />
		<exclude name="**/*-sources.jar"/>
	</fileset>
</path>
 
<!-- fuentes propias -->
<path id="fundeweb.rest.sourcepath">
	<fileset dir="${fundeweb.enunciate.home}/lib">
		<include name="**/*-sources.jar"/>
	</fileset>
	<fileset dir="${fundeweb.maven.repository}/es/um/atica/fundeweb">
		<include name="**/*-sources.jar"/>
	</fileset>
 
	<fileset dir="${fundeweb.maven.repository}/org/hibernate">
		<include name="**/*-sources.jar"/>
	</fileset>
 
	<fileset dir="${fundeweb.maven.repository}/org/jboss/seam/jboss-seam">
		<include name="**/*-sources.jar"/>
	</fileset>
</path>
 
<taskdef name="enunciate" classname="com.webcohesion.enunciate.EnunciateTask">
	<classpath refid="enunciate.classpath" />
	<classpath refid="fundeweb.rest.classpath" />
	<classpath refid="dependency.rest.classpath" />
</taskdef>
 
<enunciate basedir="${basedir}${enunciate.package.rest}"
					configFile="${basedir}/generacion/enunciate/resources/enunciate.xml" compiledebuginfo="true"
					buildDir="${basedir}/generacion/enunciate/build">
	<include name="**/*.java" />
	<classpath refid="enunciate.classpath" />
	<classpath refid="fundeweb.rest.classpath" />
	<classpath refid="dependency.rest.classpath" />
	<sourcepath refid="fundeweb.rest.sourcepath" />
</enunciate>

RAMON GINEL GEA 03/07/2019 10:07


  • fdw2.0/fundeweb2.0/gt/documentar-rest-enunciate.txt
  • Última modificación: 18/03/2020 14:20
  • por RAMON GINEL GEA