2010-05-04 9 views
5

Supponendo che io abbia uno schema che descrive una classe elemento radice Root che contiene un List<Entry> dove la classe Entry ha un nome di campo obbligatorio.Personalizzazione della gestione degli errori di unMarshall processo JAXB

Ecco come appare nel codice:

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

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

Se fornisco il seguente codice XML per unmarshalling:

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

ho un problema, perché la seconda voce non contiene un nome. Quindi unmarshall produce null.

C'è un modo per personalizzare JAXB in unmarshall di un oggetto Root che conterrà solo la voce "buona"?

risposta

5

Si potrebbe aggiungere il magic afterUnmarshal method di prendersi cura di voci vuote:

@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:

Non so se questo è più adatto per voi, ma forse è di aiuto. Puoi anche usare un Pacher, ad es. se non tutti gli oggetti che è necessario correggere/convalidare i risultati sono disponibili in afterUnmarshal (..)

Esegui da UnmarshallingContext dopo che è stata eseguita l'analisi. Utilizzato principalmente per risolvere IDREF in avanti, ma può eseguire qualsiasi azione. (Javadoc)

Ecco un esempio:

@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); 
     } 
     }); 
    } 
    } 
} 

non avrei abusarne troppo però, non solo in quanto è Sun sola API.

Ma se si sta veramente cercando qualcosa di configurabile che non faccia parte del codice degli stessi oggetti sottoposti a marshalling. Potrebbe essere meglio guardare qualcosa dopo unmarshalling. Mi chiedo se lo standard Bean Validation (JSR 303) non sia perfetto per te, ad es. utilizzando Hibernate Validator (non intimidire con il nome, non è necessario utilizzare Hibernate ORM per utilizzarlo). Non l'ho usato da solo, ma usare uno (nuovo) standard per la validazione sembra ragionevole, non è vero?

+0

è una buona idea, grazie. Ovviamente avrò bisogno di impostare eventHandler per essere tollerante per l'errore "field is required" ma non dovrebbe essere un problema. Mi chiedo se ci sia una soluzione diversa, sto cercando di rendere l'utente del mio sistema (sto scrivendo una lib per il mio gruppo che si occupa della configurazione) di essere in grado di impostare facilmente questa funzione. Posso farlo con annotazioni e qualche introspezione di classe per vedere tutti i campi che devono essere testati per il nome richiesto problema ... dentro afterUnmarshal (...). Terrò questa risposta senza risposta, forse c'è qualcuno con una risposta più adatta a ciò di cui ho bisogno. – ekeren

+0

@ekeren vedere la mia modifica, si spera che questo aiuti. Saluti – sfussenegger