Programmering

Java-XML-kortlægning gjort let med JAXB 2.0

Java Architecture for XML Binding giver en kraftfuld og praktisk måde at arbejde med XML-indhold fra Java-applikationer. Den nyligt udgivne JAXB 2.0 tilbyder mange nye funktioner, herunder fuld understøttelse af alle XML Schema-funktioner, betydeligt færre genererede klasser, genererede klasser, der er lettere at manipulere, og en mere fleksibel valideringsmekanisme.

For at forstå hvordan man behandler XML-dokumenter i Java med JAXB 2.0, skal vi se på de to vigtigste JAXB-komponenter:

  • Bindingskompileren, som binder et givet XML-skema til et sæt genererede Java-klasser
  • Den bindende runtime-ramme, der giver unmarshalling-, marshalling- og valideringsfunktioner

JAXB-bindingscompileren (eller xbj) lader dig generere Java-klasser fra et givet XML-skema. JAXB-bindingscompileren omdanner et XML-skema til en samling af Java-klasser, der matcher strukturen beskrevet i XML-skemaet. Disse klasser er kommenteret med specielle JAXB-kommentarer, som giver runtime-rammen de tilknytninger, den har brug for til at behandle de tilsvarende XML-dokumenter.

Den bindende runtime-ramme tilvejebringer en effektiv og brugervenlig mekanisme til unmarshalling (eller læsning) og marshalling (eller skrivning) af XML-dokumenter. Det giver dig mulighed for at omdanne et XML-dokument til et hierarki af Java-objekter (unmarshalling) eller omvendt omdanne et Java-objekthierarki til XML-format (marshalling). Begrebet marshalling traditionelt henviser til bortskaffelse af tropper på en passende måde. I netværk refererer det til at placere dataelementer i en buffer, før de sendes over en kommunikationskanal.

Kombineret producerer disse to komponenter en teknologi, der gør det muligt for Java-udviklere nemt at manipulere XML-data i form af Java-objekter uden at skulle kende de detaljerede detaljer i Simple API til XML-behandling (SAX) eller Document Object Model (DOM) , eller endda finesser i XML-skema.

JAXB forudsætninger

For at komme i gang med JAXB 2.0 har du brug for:

  • Java Platform, Standard Edition 5: JAXB 2.0 er stærkt afhængig af funktioner i Java SE 5, såsom kommentarer og generiske
  • En implementering af JAXB 2.0

Denne artikel blev skrevet ved hjælp af frigivelseskandidaten GlassFish JAXB.

Generer Java-klasser ved hjælp af JAXB-kompilatoren

JAXB-compileren binder et XML-skema til et sæt Java-klasser. Et XML-skema er et XML-dokument, der meget nøjagtigt beskriver de elementer og attributter, der er godkendt i en bestemt type XML-dokument. I dette eksempel bruger vi et kursusbookingssystem, der kan acceptere ordrer i XML-format. En typisk ordre ser sådan ud:

    10 Coyote Avenue, Arizona, USA 

Det tilsvarende XML-skema beskriver, hvordan uddannelseskurset er booket, og indeholder detaljer om det reserverede kursus, de tilmeldte studerende, det firma, der foretager reservationen osv. En XML-skemabeskrivelse er ekstremt streng og kan omfatte detaljer såsom antallet af elementer, der er tilladt i en liste over objekter (kardinalitet), valgfri og obligatorisk attributter og mere. Skemaet til bookingen af ​​kursusforløb (kaldet kursus-booking.xsd) vises her:

Kommandolinjeværktøjet xjc kører JAXB-kompilatoren. For at køre JAXB-kompilatoren mod vores skema, kører vi følgende kommando:

 $ xjc kursusreservation.xsd -p nz.co.equinox.training.domæne.booking -d src / genereret

Dette genererer et sæt Java-klasser, der er kommenteret med JAXB 2.0-kommentarer. Nogle af de mere nyttige muligheder er beskrevet her:

  • -d : Placer de genererede filer i denne mappe.
  • -p : Placer de genererede filer i denne pakke.
  • -nv: Udfør ikke streng validering af inputskemaet.
  • -httpproxy : Brug dette, hvis du står bag en proxy. Tager formatet [bruger [: adgangskode] @] proxyHost [: proxyPort].
  • -klassesti : Angiv om nødvendigt klassestien.
  • -Læs kun: Genererer skrivebeskyttede kildekodefiler, hvis dit operativsystem understøtter dette.

Der er også en ækvivalent myre opgave, hvilket gør det ret nemt at integrere i en Ant- eller Maven-baseret byggeproces.

Listen over genererede klasser vises her:

 CompanyType.java ContactType.java CourseBooking.java ObjectFactory.java StudentType.java

Brugere af tidligere versioner af JAXB bemærker muligvis, at dette er et glat sæt af kommenterede og fuldt dokumenterede Java-klasser snarere end det mere besværlige sæt grænseflader og implementeringer af tidligere versioner. Således har vi mindre genererede klasser og lettere og mere elegant kode. Og som du vil se i det næste afsnit, er det nemt at manipulere disse klasser.

Fjernelse af arkivering af et XML-dokument

Unmarshalling er processen med at konvertere et XML-dokument til et tilsvarende sæt Java-objekter. Det er let at afmontere i JAXB 2.0. Først opretter du en JAXBContext kontekst objekt. Kontekstobjektet er udgangspunktet for marshalling, unmarshalling og validering. Her angiver du Java-pakken, der indeholder dine JAXB-kortlagte klasser:

 JAXBContext jaxbContext = JAXBContext.newInstance ("nz.co.equinox.training.domain.booking");

For at fjerne markeringen af ​​et XML-dokument opretter du et Unmarshaller fra sammenhængen, som vist her:

 Unmarshaller unmarshaller = jaxbContext.createUnmarshaller ();

Det unmarshaller kan behandle XML-data fra en lang række datakilder: filer, inputstrømme, URL'er, DOM-objekter, SAX-parsere og mere. Her giver vi en enkel Fil objekt, der peger på vores XML-dokument. Det unmarshaller returnerer en indtastet JAXBElement, hvorfra vi kan hente vores umarmede objekt ved hjælp af getValue () metode:

JAXBElement bookingElement = (JAXBElement) unmarshaller.unmarshal (ny fil ("src / test / resources / xml / booking.xml"));

CourseBooking booking = bookingElement.getValue ();

Dokumentvalidering

Dokumentvalidering er processen med at sikre, at dit XML-dokument svarer til definitionen i det tilsvarende XML-skema. Det er et vigtigt aspekt af ethvert projekt, der involverer XML-udveksling, især hvis XML kommer fra andre systemer. Dokumentvalidering i JAXB 2.0 er lettere og mere fleksibel end i tidligere versioner. Du kan ganske enkelt vedhæfte en ValidatonEventHandler til unmarshaller inden afmontering af XML-dokumentet, som vist her:

 unmarshaller.setEventHandler (ny BookingValidationEventHandler ());

En valideringshændelseshåndterer implementerer ValidationEventHandler interface og handleEvent () metode, som vist her:

public class BookingValidationEventHandler implementerer ValidationEventHandler {

public boolean handleEvent (ValidationEvent ve) {

hvis (ve.getSeverity () == ValidationEvent.FATAL_ERROR || ve .getSeverity () == ValidationEvent.ERROR) {ValidationEventLocator locator = ve.getLocator (); // Udskriv besked fra valdationshændelse System.out.println ("Ugyldigt reservationsdokument:" + locator.getURL ()); System.out.println ("Fejl:" + ve.getMessage ()); // Output line and column number System.out.println ("Fejl ved kolonne" + locator.getColumnNumber () + ", line" + locator.getLineNumber ()); } returner sandt }}

Her udskriver vi bare detaljer om fejlen, men i en reel applikation kan en mindre triviel behandling være passende. I nogle tilfælde kan du endda overveje, at valideringsfejlen ikke er en show-stop, og at den ikke blokerer behandlingen. Ved at vende tilbage sandt, fortæller du det unmarshaller at fortsætte unmarshalling-processen: falsk ville afslutte processen med en passende undtagelse.

Opbevaring af et dokument

Marshalling indebærer at omdanne dine Java-klasser til XML-format. I JAXB 2.0 er det enkelt at oprette og manipulere disse Java-klasser. I de fleste tilfælde kan du bare behandle dem som almindelige Java-klasser, som vist her:

 CourseBooking booking = ny CourseBooking (); booking.setCourseReference ("UML-101"); booking.setTotalPrice (ny BigDecimal (10000)); ...

Bemærk, at du stadig kan bruge ObjectFactory klasse på samme måde som hvordan du brugte den i JAXB 1.0, som vist i den følgende liste. I modsætning til JAXB 1.0 er der imidlertid ingen grænseflader eller implementeringsklasser: alle domæneobjekter er bare kommenterede JavaBeans-komponenter.

 ObjectFactory-fabrik = ny ObjectFactory (); CourseBooking-booking = fabrik.createCourseBooking (); ...

Selvom de fleste XML-datatyper kortlægges direkte til normale Java-klasser, er der behov for særlig behandling for visse datatyper, f.eks. Datoer. I disse tilfælde skal du bruge DatatypeFabriksom vist her:

 DatatypeFactory datatypes = DatatypeFactory.newInstance (); booking.setCourseDate (datatyper.newXMLGregorianCalendarDate (2006,06,15,0));

Når dit domæneobjekt er initialiseret, skal du bruge JAXB-konteksten til at oprette en Marshaller objekt og en maskinskrevet JAXBElement. Oprettelse af marshaller er simpelt:

 Marshaller marshaller = jaxbContext.createMarshaller ();

Derefter opretter du en JAXBElement objekt, der indkapsler dit domæneobjekt. Den typede JAXBElement svarer til rodelementet complexType af dit XML-dokument. Brug derefter det genererede ObjectFactory klasse som følger:

 JAXBElement bookingElement = (ny ObjectFactory ()) createBooking (reservation);

I dette eksempel indstiller vi en egenskab, så output bliver formateret til menneskelig brug og derefter skriver til standardoutput:

 marshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.marshal (bookingElement, System.out);

En fuld kodeeksempel vises her:

JAXBContext jaxbContext = JAXBContext.newInstance ("nz.co.equinox.training.domain.booking");

CourseBooking booking = ny CourseBooking (); booking.setCourseReference ("UML-101"); booking.setTotalPrice (ny BigDecimal (10000)); booking.setInvoiceReference ("123456"); DatatypeFactory datatypes = DatatypeFactory.newInstance (); booking.setCourseDate (datatyper.newXMLGregorianCalendarDate (2006,06,15,0)); booking.setTotalPrice (ny BigDecimal (10000)); booking.setInvoiceReference ("123456"); booking.getStudent (). tilføj (ny StudentType ()); booking.getStudent (). get (0) .setFirstName ("John"); booking.getStudent (). get (0) .setSname ("Smith"); booking.setCompany (ny CompanyType ()); booking.getCompany (). setName ("Klienter inkl."); booking.getCompany (). setContact (ny ContactType ()); booking.getCompany (). getContact (). setName ("Paul"); booking.getCompany (). getContact (). setEmail ("[email protected]"); booking.getCompany (). getContact (). setTelephone ("12345678"); booking.getCompany (). setAddress ("10 client street");

// Marshal til System.out Marshaller marshaller = jaxbContext.createMarshaller (); JAXBElement bookingElement = (ny ObjectFactory ()) createBooking (booking); marshaller.setProperty (Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

marshaller.marshal (bookingElement, System.out);

At køre denne kode genererer noget som dette: