Passa ai contenuti principali

JAXB - Il supporto di Java all'XML



Introduzione
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. Licenza Creative Commons
Quest'opera è distribuita con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0 Internazionale.

Commenti

Post popolari in questo blog

Telecamere Ip con accesso "nascosto"

Telecamere Ip con accesso "nascosto" Storia triste di un auto-hacking obbligato che mi ha fatto scoprire come la nostra privacy è realmente messa a rischi. Storia Ho acquistato dal mercatino/fiera del Radioamatore di Fasano quattro telecamere IP. La scatola riporta "Smart Camera" LF4810. Ne ho montata una e testata in tutte le sue funzionalità per oltre un mese. Chiaramente la manualistica scarsissima, come da tradizione in questi prodotti cinesi di costo molto concorrenziale, consiste in un "pieghevole" di 4 facciate. Chiaramente non erano documentate le impostazioni necessarie per attivare i protocolli ONVIF e RTSP che mi sono indispensabili per l'uso che ne devo fare. Nonostante questa scarsa documentazione dopo l'installazione base fatta con l'apposita app: tutto sembrava corretto. Chiaramente la prima azione che ho compiuto è stata quella di cambiare la password che di default è "123". Subito dopo h...

Dynamic DNS con Duckdns.org in HTTPS

Obiettivo Avere un dominio https con certificato valido da usare come endpoint pubblico per Homeassistant e per un WebHook per i bot telegram. Fase 1 Registrazione del dominio in un servizio di dynamic DNS come https://www.duckdns.org/   : Scegliere per quale sistema operativo installare il client che si occuperà dell'aggiornamento dell'ip: Seguire la semplice guida per la configurazione del processo cron: Fase 2 Creazione del certificato e installazione sul server. Di tutto questo si occuperà una applicazione che si chiama certbot. $ sudo add-apt-repository ppa:certbot/certbot $ sudo apt install python-certbot-apache $ sudo certbot --apache -d ol3.duckdns.org -d www.ol3.duckdns.org Fase 3 Esporre il servizio https sulla rete pubblica. Aprire o reindirizzare la porta 443 verso l'host sul quale si è fatta la configurazione di certbot dal proprio router. Il certificato di certbot è valido per novanta giorn...

Wemos D1 mini ESP8266 - Aggiornamenti OTA

Wemos D1 mini - Aggiornamenti OTA Cosa è Può risultare scomodo dover collegare con un cavo usb un ESP8266 e derivati (come in questo caso un Wemos D1 mini) ad un pc per un semplice aggiornamento software.  OTA sta per "Over The Air". Con questa tecnologia si ha la possibilità di modificare il firmware di questi microcontrollori mediante la wi-fi.  Come funziona Per ottenere questa funzionalità ci si è inventato un meccanismo molto semplice: il nostro microcontrollore, dotato della capacità di aggiornamenti OTA, ha in carico un firmware che all'avvio non fa altro che, usando la libreria ArduinoOTA, collegarsi alla wi-fi (della quale avremo fornito SSID e Password) e mediante il " Multicast DNS " dichiara la sua presenza sulla WI-FI LAN, l' Ide di Arduino rileva questa presenza e ci fornisce il supporto alla comunicazione mediante wi-fi (la porta di rete rilevata prenderà il nome del modello e l'ultima parte del suo mac-address per identificarlo, se non r...