JAXB's workings and the associated development process are best understood through an example. We will quickly walk though an example and then look at different aspects of JAXB from that example in detail. OfficeMin can receive purchase orders in many ways. In , we saw how a customer such as Flute Bank can use JAXM to send XML messages. Another customer, Piggy Bank, uses a proprietary financial package but is capable of generating and saving purchase order details in XML format. OfficeMin's Web service can process these XML orders.

Generate Java Classes

The first step for OfficeMin to consume the XML is to generate the Java representation of the agreed-upon schema. We will use the schema covered in and shown in . The JAXB specifications require that all JAXB implementations provide a tool called a schema compiler or binding compiler (ScreenShot), which should be able to generate the Java code according to the rules and guidelines defined in the JAXB specification. In the reference implementation provided by Sun, the tool is called the XML-to-Java compiler (xjc).

The binding compiler

xjc can be found in the JAXB_HOME/bin directory of the reference implementation.

Execute the schema compiler on the purchase order interface:

xjc-d output generated purchaseorder.xsd

This will generate two sets of files:

Write app Code

The app in the example reads in an XML file and does something useful (for now, it just changes some information around) and writes out an XML file. The file we will read in, purchaseorder.xml, was used in .Listing 13.2: Simple JAXB code to read an XML document

import java.io.*;
import java.util.*;
// import JAXB API import javax.xml.bind.*;
// import java content classes generated by binding compiler import com.flutebank.schema.*;
public class ReadWritePO {
 public static void main( String[] args ) throws Exception {
// create a JAXBContext capable of handling classes in the generated package
 JAXBContext context = JAXBContext.newInstance( "com.flutebank.schema" );
// create an Unmarshaller
 Unmarshaller unmars = context.createUnmarshaller();
// unmarshall an XML document into its Java representation
 Purchaseorder po = (Purchaseorder)unmars.unmarshall( new FileInputStream(
"purchaseorder.xml" ) );
// display the shipping address
 Billingaddress address = po.getBillingaddress();
 Name name= address.getName();
 Street street= address.getStreet();
 City city= address.getCity();
 State state = address.getState();
 Zip zip= address.getZip();
 System.out.println( "Billing address in the XML is : " );
 System.out.println("Name :" + name.getValue());
 System.out.println("Street :" + street.getValue());
 System.out.println("City :" + city.getValue());
 System.out.println("State :" + state.getValue());
 System.out.println("Zip :" + zip.getValue());
 Items order=po.getItems();
 Iterator it=order.getItem().iterator();
 while(it.hasNext()){
 Item item= (Item)it.next();
 System.out.println("Order contains" );
 System.out.println(" Description: " + item.getDescription().getValue());
 System.out.println(" Product number: " +
 item.getProductnumber().getValue());
 System.out.println(" Quantity: " + item.getQuantity().getValue());
 System.out.println(" Unit cost: " + item.getUnitcost().getValue());
 }
// Change some information
 name.setValue("Sameer Tyagi");
 zip.setValue("90210");
// Marshall Java to XML
 Marshaller mars = context.createMarshaller();
 mars.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
 mars.setProperty (Marshaller.JAXB_SCHEMA_LOCATION," http://www.flutebank.com/schema
 purchaseorder.xsd");
 mars.marshall( po, new FileOutputStream("modifiedpurchaseorder.xml"));
 }
}

It should be apparent that the code in does not involve any parsing logic whatsoever. The app code uses the JAXB API (e.g., Unmarshaller and JAXBContext) when dealing with the marshalling and unmarshalling and uses the generated interfaces when dealing with the object representation. shows the output saved in modifiedpurchaseorder.xml.Listing 13.3: The XML marshalled out by app code in Listing 13.2

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:purchaseorder xsi:schemaLocation="http://www.flutebank.com/schema purchaseorder.xsd" xmlns:ns1="http://www.flutebank.com/schema" xmlns:xsi="http://
www.w3.org/2001/XMLSchema-instance">
 <ns1:identifier>87 6784365876JHITRYUE</ns1:identifier>
 <ns1:date>29 October 2002</ns1:date>
 <ns1:billingaddress>
 <ns1:name>Sameer Tyagi</ns1:name>
 <ns1:street>256 Eight Bit Lane</ns1:street>
 <ns1:city>Burlington</ns1:city>
 <ns1:state>MA</ns1:state>
 <ns1:zip>90210</ns1:zip>
 </ns1:billingaddress>
 <ns1:items>
 <ns1:item>
 <ns1:quantity>3</ns1:quantity>
 <ns1:productnumber>229AXH</ns1:productnumber>
 <ns1:description>High speed photocopier machine with automatic sensors
 </ns1:description>
 <ns1:unitcost>1939.99</ns1:unitcost>
 </ns1:item>
 <ns1:item>
 <ns1:quantity>1</ns1:quantity>
 <ns1:productnumber>1632</ns1:productnumber>
 <ns1:description>One box of color toner cartridges</ns1:description>
 <ns1:unitcost>43.95</ns1:unitcost>
 </ns1:item>
 </ns1:items>
</ns1:purchaseorder>

The preceding example should have helped clarify how JAXB works and the simplified approach it provides to developers. No more parsing! Looking at , it should also be apparent that it has two parts:

Let us now look at the underpinnings of JAXB in these two areas.