2010-05-04 13 views
5

Angenommen, ich habe ein Schema, das eine Stammelementklasse Root beschreibt, die eine List<Entry> enthält, wobei die Klasse Entry einen erforderlichen Feldnamen hat.Anpassen der Fehlerbehandlung des JAXB-Prozesses von marmarshall

Hier ist, wie es im Code aussieht:

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

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

Wenn ich die folgende XML für unmarshalling liefern:

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

Ich habe ein Problem, weil der zweite Eintrag keinen Namen enthalten. So produziert Unmarshall null.

Gibt es eine Möglichkeit JAXB zu gestalten ein Root Objekt entordnen, die nur die „guten“ Eintrag enthalten wird?

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

nicht sicher, ob dies besser geeignet für Sie, aber vielleicht ist es von Hilfe

Antwort

5

Sie konnten die magic afterUnmarshal method kümmern leeren Einträge hinzufügen. Sie könnten auch einen Pacher, z.B. Wenn nicht alle Objekte, die Sie zur Korrektur/Validierung Ihres Ergebnisses benötigen, in AfterUnmarshal (..) verfügbar sind

Wird von UnmarshallingContext ausgeführt, nachdem alle Parsing durchgeführt wurde. Wird hauptsächlich zum Auflösen von IDREFs verwendet, kann jedoch beliebige Aktionen ausführen. (Javadoc)

Hier ist ein Beispiel:

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

Ich würde nicht missbrauchen es aber zu viel, nicht nur, wie es Sun-only-API ist.

Aber wenn Sie wirklich etwas konfigurierbar suchen, das nicht Teil des Codes der Marshalled-Objekte selbst ist. Es ist vielleicht am besten, sich nach dem Entpacken etwas anzusehen. Ich frage mich, ob Bean Validation (JSR 303) wäre nicht perfekt für Sie, z. Verwenden Sie Hibernate Validator (nicht durch den Namen eingeschüchtert werden, benötigen Sie nicht Hibernate ORM, um es zu verwenden). Ich habe es selbst nicht benutzt, aber die Verwendung eines (neuen) Standards für die Validierung klingt vernünftig, nicht wahr?

+0

ist es eine gute Idee, Danke. Natürlich muss ich den eventHandler für den "field is required" Fehler tolerant einstellen, aber es sollte kein Problem sein. Ich frage mich, ob es eine andere Lösung gibt, ich versuche, den Benutzer meines Systems zu machen (ich schreibe eine Lib für meine Gruppe, die sich mit der Konfiguration beschäftigen), um diese Funktion einfach einstellen zu können. Ich kann es mit Annotation und einigen Klassenintrospektion tun, um alle Felder zu sehen, die auf den Namen, den ich benötige, zu testen ... innerhalb von AfterUnmarshal (...). Ich werde dies unbeantwortet lassen, vielleicht gibt es jemanden mit einer passenderen Antwort für das, was ich brauche. – ekeren

+0

@ekeren sehe meine Bearbeitung, hoffentlich hilft das. Prost – sfussenegger