Generador de Tag Library Descriptor usando JAXB y Procesador de anotaciones

Estoy realizando modificaciones a mi proyecto de generación de archivos TLD (archivo XML para la definición de etiquetas para JSP).

Anteriormente el archivo TLD se generaba con Stax pero consideré que era prudente reducir el código para hacer más fácil las actividades de mantenimiento. El proyecto ya contenia clases bean cuyas propiedades eran directamente escritas a elementos o atributos XML con Stax. No había utilizado antes JAXB pero sabía que es un API para la traducción de XML/ Java (en forma bidireccional) por lo que realizé algunas pruebas preliminares y funcionaba de forma muy cercana a lo que yo esperaba.

Éste es un ejemplo de una clase en mi proyecto que contiene anotaciones de JAXB para poder ser traducida a XML.


package tldgen.processor;

import java.util.LinkedList;
import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement(name="taglib")
@XmlType(propOrder={"description", "displayName", "icon", "libraryVersion", "shortName", "uri", "validator", "webListeners", "tagFiles", "tagHandlers", "functions"})
public class TagLibraryInfo {
    private String uri;
    private String description;
    private String displayName;
    private String icon;
    private String libraryVersion;
    private String jspVersion;
    private String shortName;
    private List<TagInfo> tagHandlers=new LinkedList<TagInfo>();
    private List<FunctionInfo> functions=new LinkedList<FunctionInfo>();
    private ValidatorInfo validator;
    private List<WebListenerInfo> webListeners=new LinkedList<WebListenerInfo>();
    private List<TagFileInfo> tagFiles=new LinkedList<TagFileInfo>();

    protected TagLibraryInfo() {
    }
    
    public TagLibraryInfo(String uri) {
        this.uri = uri;
    }

    @XmlElement
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @XmlElement(name="display-name")
    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    @XmlElement
    public String getIcon() {
        return icon;
    }

    public void setIcon(String icon) {
        this.icon = icon;
    }

    @XmlElement(name="short-name")
    public String getShortName() {
        return shortName;
    }

    public void setShortName(String shortName) {
        this.shortName = shortName;
    }

    @XmlElement
    public String getUri() {
        return uri;
    }

    @XmlElement(name="tlib-version")
    public String getLibraryVersion() {
        return libraryVersion;
    }

    public void setLibraryVersion(String version) {
        this.libraryVersion = version;
    }

    @XmlAttribute(name="version")
    public String getJspVersion() {
        return jspVersion;
    }

    public void setJspVersion(String jspVersion) {
        this.jspVersion = jspVersion;
    }

    public ValidatorInfo getValidator() {
        return validator;
    }

    @XmlElement
    public void setValidator(ValidatorInfo validator) {
        this.validator = validator;
    }
    
    @XmlElement(name="tag")
    List<TagInfo> getTagHandlers() {
        return tagHandlers;
    }

    @XmlElement(name="function")
    List<FunctionInfo> getFunctions() {
        return functions;
    }

    @XmlElement(name="tag-file")
    List<TagFileInfo> getTagFiles() {
        return tagFiles;
    }

    @XmlElement(name="listener")
    List<WebListenerInfo> getWebListeners() {
        return webListeners;
    }
    
}

Para definir el namespace del archivo TLD, incluí el archivo package-info.java  (ver anotaciones en paquetes) con el siguiente contenido:

@XmlSchema(
namespace = "http://java.sun.com/xml/ns/javaee",
elementFormDefault = XmlNsForm.QUALIFIED)

package tldgen.processor;

import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

Aquí hay un ejemplo de una clase que invoca JAXB para realizar la conversión:


package tldgen.processor;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import tldgen.BodyContentType;

public class Main {
    
    public static void main(String[] args) throws JAXBException {
        TagLibraryInfo info=new TagLibraryInfo("http://simplehtml.net");
        info.setJspVersion("2.1");
        info.setLibraryVersion("1.0");
        info.setDescription("Tags for common HTML elements");
        info.getFunctions().add(
             new FunctionInfo("sum", "functions.Sum", "int sum(int a, int b)"));
        info.getFunctions().add(
             new FunctionInfo("sum2", "functions.Sum", "int sum(int a, int b)"));
        TagInfo tagInfo = new TagInfo("img", "my.ImageTag", BodyContentType.TAG_DEPENDENT);
        AttributeInfo attributeInfo = new AttributeInfo("src");
        attributeInfo.setType("java.lang.String");
        tagInfo.getAttributes().add(attributeInfo);
        info.getTagHandlers().add(tagInfo);
        JAXBContext context=JAXBContext.newInstance(TagLibraryInfo.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, 
          "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd");
        m.marshal(info, System.out);
    }
    
}

Y este es el XML generado:


run:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
    <description>Tags for common HTML elements</description>
    <tlib-version>1.0</tlib-version>
    <uri>http://simplehtml.net</uri>
    <tag>
        <name>img</name>
        <tag-class>my.ImageTag</tag-class>
        <body-content>tagdependent</body-content>
        <attribute>
            <name>src</name>
            <type>java.lang.String</type>
        </attribute>
    </tag>
    <function>
        <name>sum</name>
        <function-class>functions.Sum</function-class>
        <function-signature>int sum(int a, int b)</function-signature>
    </function>
    <function>
        <name>sum2</name>
        <function-class>functions.Sum</function-class>
        <function-signature>int sum(int a, int b)</function-signature>
    </function>
</taglib>


Ahora que estoy utilizando JAXB en el proyecto, creo que dispondré de tiempo que ocuparé en otros módulos del generador (como el procesador de anotaciones) o en otros proyectos.

El tutorial que utilice se encuentra en este enlace http://jaxb.java.net/tutorial/.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s