2010-05-04 8 views
5

Suponiendo que tengo un esquema que describe un elemento raíz clase Root que contiene un List<Entry> donde la clase Entry tiene un nombre de campo obligatorio.Personalización de la gestión de errores del proceso unmarshall JAXB

Aquí es cómo se ve en código:

@XmlRootElement 
class Root{ 
    @XmlElement(name="entry") 
    public List<Entry> entries = Lists.newArrayList(); 
} 

@XmlRootElement 
class Entry{ 
    @XmlElement(name="name",required=true) 
    public String name; 
} 

Si yo proporciono el siguiente código XML para unmarshalling:

<root> 
    <entry> 
    <name>ekeren</name> 
    </entry> 
    <entry> 
    </entry> 
</root> 

tengo un problema porque la segunda entrada no contiene un nombre. Entonces unmarshall produce null.

¿Hay alguna manera de personalizar JAXB para separar un objeto Root que solo contendrá la entrada "buena"?

Respuesta

5

Se podría añadir el magic afterUnmarshal method para cuidar de entradas vacías:

@XmlRootElement 
class Root{ 
    @XmlElement(name="entry") 
    public List<Entry> entries = Lists.newArrayList(); 

    void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) { 
    Iterator<Entry> iter = entries.iterator(); 
    while (iter.hasNext()) { 
     if (iter.next().name == null) iter.remove(); 
    } 
    } 
} 

EDIT:

No estoy seguro si esto es más adecuado para usted, pero tal vez sea de ayuda. También puedes usar un Pacher, p. si no todos los objetos que necesita para corregir/validar su resultado están disponibles en afterUnmarshal (..)

Ejecutado por UnmarshallingContext después de todo el análisis se hace. Principalmente utilizado para resolver IDREF hacia adelante, pero puede ejecutar cualquier acción. (Javadoc)

He aquí un ejemplo:

@XmlRootElement 
class Entry{ 
    @XmlElement(name="name",required=true) 
    public String name; 

    private boolean isValidEntry() { 
    return name != null; 
    } 

    void afterUnmarshal(final Unmarshaller unmarshaller, final Object parent) { 
    if (!isValidEntry()) { 
     // entry not yet added to parent - use a patcher 
     UnmarshallingContext.getInstance().addPatcher(new Patcher() { 
     public void run() throws SAXException { 
      ((Root)parent).removeEntry(this); 
     } 
     }); 
    } 
    } 
} 

yo no abusar de ella demasiado sin embargo, no sólo ya que es única Sun-API.

Pero si realmente está buscando algo configurable que no forme parte del código de los objetos ordenados. Quizás sea mejor mirar algo después de desmantelar. Me pregunto si Bean Validation (JSR 303) no sería el ajuste perfecto para usted, p. usando Hibernate Validator (no se deje intimidar por el nombre, no necesita Hibernate ORM para usarlo). No lo he usado yo mismo, pero el uso de un (nuevo) estándar para la validación suena razonable, ¿no?

+0

es una buena idea, gracias. Por supuesto, tendré que configurar eventHandler para que sea tolerante con el error "se requiere campo" pero no debería ser un problema. Me pregunto si hay una solución diferente, estoy tratando de hacer que el usuario de mi sistema (estoy escribiendo una lib para mi grupo que se ocupa de la configuración) pueda establecer fácilmente esta característica. Puedo hacerlo con anotación y una introspección de clase para ver todos los campos que necesitan ser probados para el problema de nombre requerido ... dentro afterUnmarshal (...). Mantendré esto sin respuesta, tal vez haya alguien con una respuesta más adecuada para lo que necesito. – ekeren

+0

@ekeren mira mi edición, afortunadamente eso ayuda. aclamaciones – sfussenegger

Cuestiones relacionadas