In this section we'll show how to create XML from the beans generated earlier.
XML (or better an XML document) exists in various
flavours: you might want to have it serialized into a String or you may prefer character or
byte streams (typically instances of Writer
or OutputStream
).
In other cases, a DOM representation is more useful. Feeding SAX events to a pipeline may be more
efficient on other occasions.
The important questions are: how do I create a serialized XML document (a String, a character or byte stream)? And, vice versa, how do I read such a document and convert it back into Java objects?
In the case of JaxMe, you'll start from simple Java beans whose source has typically
been generated. An address implementation is constructed by instantiating
an AddressImpl
(which implements Address
).
For example:
import java.io.FileWriter; import java.io.Writer; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import org.apache.ws.jaxme.examples.misc.address.Address; import org.apache.ws.jaxme.examples.misc.address.AddressType.EmailDetailsType.EmailType; import org.apache.ws.jaxme.examples.misc.address.AddressType.PhoneDetailsType.PhoneType; import org.apache.ws.jaxme.examples.misc.address.impl.AddressImpl; import org.apache.ws.jaxme.examples.misc.address.impl.AddressTypeImpl.EmailDetailsTypeImpl; import org.apache.ws.jaxme.examples.misc.address.impl.AddressTypeImpl.EmailDetailsTypeImpl.EmailTypeImpl; import org.apache.ws.jaxme.examples.misc.address.impl.AddressTypeImpl.PhoneDetailsTypeImpl; import org.apache.ws.jaxme.examples.misc.address.impl.AddressTypeImpl.PhoneDetailsTypeImpl.PhoneTypeImpl; import org.apache.ws.jaxme.examples.misc.address.impl.AddressTypeImpl.NameTypeImpl; import org.apache.ws.jaxme.examples.misc.address.impl.AddressTypeImpl.PostalTypeImpl; public class AddressCreator { public static void writeAddress(Writer pWriter) throws JAXBException { // Create the element: Address addr = new AddressImpl(); addr.setName(new NameTypeImpl()); addr.getName().setFirst("Jane"); addr.getName().setLast("Doe"); addr.setPostal(new PostalTypeImpl()); addr.getPostal().setStreet("34 Main Street"); addr.getPostal().setCity("Boston"); addr.getPostal().setState("MA"); addr.getPostal().setZIP("02215"); addr.setEmailDetails(new EmailDetailsTypeImpl()); /* Lots of similar lines omitted for brevity ... * ... */ // And save it into the file "Address.xml" JAXBContext context = JAXBContext.newInstance("org.apache.ws.jaxme.examples.misc.address"); Marshaller marshaller = context.createMarshaller(); marshaller.marshal(addr, pWriter); } public static void main(String[] args) throws Exception { FileWriter fw = new FileWriter("Address.xml"); writeAddress(fw); fw.close(); } }The complete example code can be found in the JaxMe distribution (
src/java/org/apache/ws/jaxme/examples/misc/address/AddressCreator.java
).
There are several things you should note here:
JAXBContext
and Marshaller
are used. These objects are specified by
JAXB. The example uses no JaxMe specific
features and should run with any compliant JAXB implementation.The example on writing XML was surprisingly simple. In fact, the only nasty part was creating the object, which requires invocation of lots of setters and getters. Quite opposed to the marshalling, which took place in three lines. And, as we soon will see: unmarshalling (the process of reading a document) is by no means more complex.
To demonstrate the unmarshalling process, we'll quote an example from
the JaxMe distribution again. This time it's the file
src/java/org/apache/ws/jaxme/examples/misc/address/AddressPrinter.java
:
package org.apache.ws.jaxme.examples.misc.address; import java.io.File; import java.io.FileInputStream; import java.io.StringWriter; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.apache.ws.jaxme.examples.misc.address.Address; import org.xml.sax.InputSource; public class AddressPrinter { public static Address getAddress(InputSource pSource) throws JAXBException { JAXBContext context = JAXBContext.newInstance("org.apache.ws.jaxme.examples.misc.address"); Unmarshaller unmarshaller = context.createUnmarshaller(); return (Address) unmarshaller.unmarshal(pSource); } public static String getAddressAsString(Address pAddress) throws JAXBException { StringWriter sw = new StringWriter(); JAXBContext context = JAXBContext.newInstance("org.apache.ws.jaxme.examples.misc.address"); Marshaller marshaller = context.createMarshaller(); marshaller.marshal(pAddress, sw); return sw.toString(); } public static void main(String[] args) throws Exception { File f = new File("Address.xml"); InputSource isource = new InputSource(new FileInputStream(f)); isource.setSystemId(f.toURL().toString()); Address addr = getAddress(isource); // A simpler variant might be: // Address addr = unmarshaller.unmarshal(f); if (addr.getName() == null) { System.out.println("Loaded address without name."); } else { System.out.println("Loaded address " + addr.getName().getLast() + ", " + addr.getName().getFirst() + "."); } System.out.println("Details:" + getAddressAsString(addr)); } }
How this example works:
Address.xml
. This is the
very same file created in the first example. JaxMe supports true round-tripping.InputSource
is constructed. The
InputSource
is part of the SAX
API and can be viewed as an abstract data source from which XML can be read.
Typically, the InputSource
will be backed by
an InputStream
or a Writer
.getAddress()
is invoked
to convert the XML document into an instance of Address.
These are the promised three lines, again using classes and methods
specified by JAXB.getAddressAsString
is invoked to convert the Address instance back into a
printable String, which we may use to verify that everything went fine.
(It is always nice to see a result being displayed on the screen. :-)