2010-05-04 12 views
5

Zakładając, że mam schemat, który opisuje klasę elementu głównego Root, która zawiera List<Entry>, gdzie klasa Entry ma wymaganą nazwę pola.Dostosowywanie obsługi błędów procesu unmarshall JAXB

Oto jak to wygląda w kodzie:

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

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

Gdybym podać następujące XML dla unmarshalling:

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

mam problem ponieważ drugi wpis nie zawiera nazwy. Tak więc unmarshall produkuje null.

Czy istnieje sposób na dostosowanie JAXB do usunięcia obiektu Root, który będzie zawierał tylko "dobry" wpis?

Odpowiedz

5

Można dodać magic afterUnmarshal method dbać o pustych wpisów:

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

Nie jestem pewien, czy to jest lepiej nadaje się dla ciebie, ale może to pomóc. Możesz także użyć Pachera, np. jeśli nie wszystkie obiekty, które musisz naprawić/sprawdzić poprawność wyniku, są dostępne po Aftermnarshal (..)

Uruchamia się przez UnmarshallingContext po zakończeniu wszystkich analiz. Przede wszystkim używane do rozstrzygnięcia forward IDREF, ale może uruchomić dowolną akcję. (Javadoc)

Oto przykład:

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

Nie chciałbym nadużywać go zbyt dużo, choć nie tylko, jak to jest tylko Sun-API.

Ale jeśli naprawdę interesujesz się czymś konfigurowalnym, który nie jest częścią kodu samego uporządkowanego obiektu. Najlepiej byłoby po prostu spojrzeć na coś po usunięciu z mapy. Zastanawiam się, czy Bean Validation (JSR 303) nie byłoby idealne dla Ciebie, np. używając Hibernate Validator (nie daj się zastraszyć przez nazwę, nie potrzebujesz Hibernacji ORM, aby go użyć). Nie używałem go osobiście, ale użycie standardu (nowego) do sprawdzania poprawności brzmi rozsądnie, prawda?

+0

to jest dobry pomysł, dzięki. Oczywiście będę musiał ustawić eventHandler, aby był tolerancyjny dla błędu "pole jest wymagane", ale nie powinien to być problem. Zastanawiam się, czy istnieje inne rozwiązanie, próbuję uczynić użytkownika mojego systemu (piszę bibliotekę dla mojej grupy, która zajmuje się konfiguracją), aby móc łatwo ustawić tę funkcję. Mogę to zrobić za pomocą adnotacji i introspekcji klas, aby zobaczyć wszystkie pola, które muszą być przetestowane pod kątem wymaganego problemu nazwy ... wewnątrz afterUnmarshal (...). Będę trzymać to bez odpowiedzi, może jest ktoś z bardziej odpowiadającą odpowiedzią na to, czego potrzebuję. – ekeren

+0

@ekeren zobacz moją edycję, mam nadzieję, że to pomaga. Twoje zdrowie – sfussenegger

Powiązane problemy