Ho fatto una sintesi dell'ottimo articolo di Marco Parente che approfondisce perfettamente JAXB.
JAXB
"Java Architecture for XML Binding" è un framework di supporto di XML per Java.
Dalla versione 1.6 di Java SE il framework JAXB è incluso e fornisce una serie di API completa per la gestione dei documenti XML.
Le applicazioni più comuni di XML+Java sono SAX (Simple API for XML) e DOM (Document Object Model) e appartengono entrambe al pacchetto JAXP (Java API for XML Processing) che vengono utilizzate per effettuare l'analisi dei documenti XML.
SAX non salva nulla in memoria e il documento viene letto dall'inizio alla fine. Quindi non sono disponibili in queste API operazioni che richiedono la memorizzazione del documento o parti di esso.
DOM memorizza l'intero documento in memoria e quindi sono messi a disposizione strumenti per analizzare e/o modificare i dati.
JAXB fornisce una astrazione tale che non richiede la conoscenza del contenuto dell'XML. Tutto questo grazie a tre operazioni principali:
- Binding
- Unmarshalling
- Marshalling
Per illustrare gli strumenti messi a disposizione da JAXB si costruirà il seguente progetto:
Binding
Questa operazione è rivolta all'accesso al documento e consiste nella generazione di una serie di classi Java che rappresentano lo schema che si vuole accedere e la creazione delle classi, istanza dello schema definito, mediante un apposito compilatore che si chiama "xjc".
Nelle cartelle All e Schemi definiamo i file xsd che descrivono il nostro schema di esempio, quello di una pianta che richiama altri schemi definiti sotto:
Pianta.xsd
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema
xmlns:sc2="http://www.flora.bindings.com"
xmlns:sc1="http://www.elementiBase.bindings.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.flora.bindings.com">
<xs:import namespace="http://www.elementiBase.bindings.com" schemaLocation="../Schemi/Radice.xsd" />
<xs:import namespace="http://www.elementiBase.bindings.com" schemaLocation="../Schemi/Fusto.xsd" />
<xs:import namespace="http://www.elementiBase.bindings.com" schemaLocation="../Schemi/Foglia.xsd" />
<xs:element name="Pianta">
<xs:complexType>
<xs:sequence>
<xs:element name="Nome" element="xs:string" />
<xs:element ref="sc1:TipologiaRadice" />
<xs:element ref="sc1:CaratteristicheFusto" />
<xs:element ref="sc1:CaratteristicheFoglie" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Radice.xsd
<?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:sc1="http://www.elementiBase.bindings.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.elementiBase.bindings.com"><xs:import namespace="http://www.w3.org/2001/XMLSchema" /><xs:element name="TipologiaRadice"> <xs:complexType> <xs:sequence> <xs:element name="Ramificazione" type="xs:string" /> <xs:element name="Resistenza" type="xs:string" /> </xs:sequence> </xs:complexType></xs:element></xs:schema>
Fusto.xsd
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema
xmlns:sc1="http://www.elementiBase.bindings.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.elementiBase.bindings.com">
<xs:import namespace="http://www.w3.org/2001/XMLSchema" />
<xs:element name="CaratteristicheFusto">
<xs:complexType>
<xs:sequence>
<xs:element name="Tipo" type="xs:string" />
<xs:element name="Spessore" type="xs:int" />
<xs:element name="Altezza" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Foglia.xsd
<?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:sc1="http://www.elementiBase.bindings.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.elementiBase.bindings.com"><xs:import namespace="http://www.w3.org/2001/XMLSchema" /><xs:element name="CaratteristicheFoglie"> <xs:complexType> <xs:sequence> <xs:element name="Tipo" type="xs:string" /> <xs:element name="Forma" type="xs:string" /> </xs:sequence> </xs:complexType></xs:element></xs:schema>
Dagli schemi si passa alla produzione delle classi grazie all'utilitàxjc da lanciare semplicemente posizionandosi con la shell a riga di comando nella cartella "All":
xjc -nv Pianta.xsd
Verranno generate tutte le classi usate da Pianta nel rispetto del namespace definito che conterranno i metodi get e set in perfetto stile java beans.
Il mapping tra XML e Java viene implementato mediante delle annotazioni. Per ogni package vengono definite due classi:
package-info.java : è il descrittore del package con la responsabilità di importare le librerie contenenti le annotazioni JAXB
ObjectFactory.java : consente di creare oggetti a run-time in seguito ad azioni dell'utente o del flusso di informazioni.
Unmarshalling
Effettuare l'Unmarshalling di un documento XML significa creare un albero di oggetti che rappresenta il contenuto e l'organizzazione del documento.
Per effettuare l'unmarshalling occorre istanziare un oggetto JAXBContext, un oggetto Unmarshaller e invocare il metodo.JAXBContext : fornisce l'entry point per le API specificando una lista di uno o più nomi di package che contengono le interfacce generate da un binding compiler.
Unmarshaller: controlla il processo di unmarshalling del documento XML passato sotto forma di file. Ciò che viene restituito è un oggetto che può essere castato.
Sotto il pezzo di codice che invoca il metodo, istruendolo, e restituisce l'oggetto castato.
...
static String filePath = "xmlExample/pianta.xml";
static String context = "com.bindings.flora";
static JaxbUnmarshal unmarshall = new JaxbUnmarshal(filePath, context);
static Pianta piantaObj = (Pianta) unmarshall.getUnmarshalledObject();
...
Il casting consente di tenere la classe JaxbUnmarshal rimane generica.
Se si volesse accedere ai dati del file XML senza farne l'unmarshalling è possibile utilizzare i metodi set degli oggetti ObjectFactory generati dal compilatore.
...Pianta nuovapianta = new Pianta();nuovapianta.setNome("Alloro"); CaratteristicheFusto fustoAlloro = new CaratteristicheFusto();fustoAlloro.setSpessore(1);fustoAlloro.setAltezza(8);nuovapianta.setCaratteristicheFusto(fustoAlloro);...
Interessante notare la disponibilità del metodo setValidating() della classe Unmarshaller.
Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale.
Commenti
Posta un commento