Processing a UBL Order Instance with JAXB-Generated Classes

Links on this page open their targets in a second window. If clicking on a link seems not to do anything, that's probably because that window is covered or minimized.

This sample processes a business order instance, as defined by UBL (Universal Business Language). It shows how JAXB helps when developing applications for industry-standard schema. The best thing is to start by running the sample, especially since many of the links in this document refer to the output.

Running the Sample

Solaris/Unix

$ JWSDP_HOME=<Your Java WSDP installation directory>
$ $JWSDP_HOME/apache-ant/bin/ant

Windows NT/2000/XP

> set JWSDP_HOME=<Your Java WSDP installation directory>
> %JWSDP_HOME%\apache-ant\bin\ant

This directory structure exists before running the project:

./cd-UBL-1.0 ) Subset of the bundle obtained from
| |          ) http://docs.oasis-open.org/ubl/cd-UBL-1.0.zip
| |
| ./xml/office ) Instance documents
| |     |                                  ) Order instance
| |     ./UBL-Order-1.0-Office-Example.xml ) processed by
| |                                        ) this sample
| |
| ./xsd ) The UBL schema
|  |
|  ./codelist
|  | |
|  | ./UBL-CodeList-AcknowledgementResponseCode-1.0.xsd
|  | ./UBL-CodeList-AllowanceChargeReasonCode-1.0.xsd
|  | ./UBL-CodeList-ChannelCode-1.0.xsd
|  | ./UBL-CodeList-ChipCode-1.0.xsd
|  | ./UBL-CodeList-CountryIdentificationCode-1.0.xsd
|  | ./UBL-CodeList-CurrencyCode-1.0.xsd
|  | ./UBL-CodeList-DocumentStatusCode-1.0.xsd
|  | ./UBL-CodeList-LatitudeDirectionCode-1.0.xsd
|  | ./UBL-CodeList-LineStatusCode-1.0.xsd
|  | ./UBL-CodeList-LongitudeDirectionCode-1.0.xsd
|  | ./UBL-CodeList-OperatorCode-1.0.xsd
|  | ./UBL-CodeList-PaymentMeansCode-1.0.xsd
|  | ./UBL-CodeList-SubstitutionStatusCode-1.0.xsd
|  |
|  ./common
|  | |
|  | ./UBL-CommonAggregateComponents-1.0.xsd
|  | ./UBL-CommonBasicComponents-1.0.xsd
|  | ./UBL-CoreComponentParameters-1.0.xsd
|  | ./UBL-CoreComponentTypes-1.0.xsd
|  | ./UBL-SpecializedDatatypes-1.0.xsd
|  | ./UBL-UnspecializedDatatypes-1.0.xsd
|  |
|  ./maindoc
|    |
|    ./UBL-DespatchAdvice-1.0.xsd
|    ./UBL-Invoice-1.0.xsd
|    ./UBL-Order-1.0.xsd
|    ./UBL-OrderCancellation-1.0.xsd
|    ./UBL-OrderChange-1.0.xsd
|    ./UBL-OrderResponse-1.0.xsd
|    ./UBL-OrderResponseSimple-1.0.xsd
|    ./UBL-ReceiptAdvice-1.0.xsd
|
./build.xml
|
./docs
| |
| ./index.html  )
| ./output.html ) Sample-specific documentation
| ./xjb.html    )
|
./src ) Application source code
| |
| ./samples/ubl/report ) Application package
|               |
|               ./PrintOrder.java ) Order printing
|               |                 ) application
|               |
|               ./facade ) Code implementing the
|                 |      ) facade design pattern
|                 |
|                 ./AddressFacade.java
|                 ./OrderFacade.java
|                 ./OrderLineTypeFacade.java
|
./ubl.xjb ) Binding customizations

Running the project creates the directories gen-src and classes.

          ) Java bindings created by processing
./gen-src ) UBL schema with xjc using custom-
| |       ) izations in ubl.xjb.
| |
| ./org/oasis/ubl/codelist/acknowledgementresponse
| ./org/oasis/ubl/codelist/allowancechargereason
| ./org/oasis/ubl/codelist/channel
| ./org/oasis/ubl/codelist/chip
| ./org/oasis/ubl/codelist/countryidentification
| ./org/oasis/ubl/codelist/currency
| ./org/oasis/ubl/codelist/documentstatus
| ./org/oasis/ubl/codelist/latitudedirection
| ./org/oasis/ubl/codelist/linestatus
| ./org/oasis/ubl/codelist/longitudedirection
| ./org/oasis/ubl/codelist/operator
| ./org/oasis/ubl/codelist/paymentmeans
| ./org/oasis/ubl/codelist/substitutionstatus
| ./org/oasis/ubl/commonaggregatecomponents
| ./org/oasis/ubl/commonbasiccomponents
| ./org/oasis/ubl/corecomponentparameters
| ./org/oasis/ubl/corecomponenttypes
| ./org/oasis/ubl/despatchadvice
| ./org/oasis/ubl/invoice
| ./org/oasis/ubl/order
| ./org/oasis/ubl/ordercancellation
| ./org/oasis/ubl/orderchange
| ./org/oasis/ubl/orderresponse
| ./org/oasis/ubl/orderresponsesimple
| ./org/oasis/ubl/receiptadvice
| ./org/oasis/ubl/specializeddatatypes
| ./org/oasis/ubl/unspecializeddatatypes
|
./classes ) Packages for the compiled bindings
  |       ) and application code.
  |
  ./org/oasis/ubl/codelist/acknowledgementresponse
  ./org/oasis/ubl/codelist/allowancechargereason
  ./org/oasis/ubl/codelist/channel
  ./org/oasis/ubl/codelist/chip
  ./org/oasis/ubl/codelist/countryidentification
  ./org/oasis/ubl/codelist/currency
  ./org/oasis/ubl/codelist/documentstatus
  ./org/oasis/ubl/codelist/latitudedirection
  ./org/oasis/ubl/codelist/linestatus
  ./org/oasis/ubl/codelist/longitudedirection
  ./org/oasis/ubl/codelist/operator
  ./org/oasis/ubl/codelist/paymentmeans
  ./org/oasis/ubl/codelist/substitutionstatus
  ./org/oasis/ubl/commonaggregatecomponents
  ./org/oasis/ubl/commonbasiccomponents
  ./org/oasis/ubl/corecomponentparameters
  ./org/oasis/ubl/corecomponenttypes
  ./org/oasis/ubl/despatchadvice
  ./org/oasis/ubl/invoice
  ./org/oasis/ubl/order
  ./org/oasis/ubl/ordercancellation
  ./org/oasis/ubl/orderchange
  ./org/oasis/ubl/orderresponse
  ./org/oasis/ubl/orderresponsesimple
  ./org/oasis/ubl/receiptadvice
  ./org/oasis/ubl/specializeddatatypes
  ./org/oasis/ubl/unspecializeddatatypes
  ./samples/ubl/report
  ./samples/ubl/report/facade

Interpreting the Output

If this is the first time you've run the sample, you'll see output similar to this. Here's what's happening in each step.

Creating the Javadoc

To create the Javadoc on, e.g., Unix:

$ $JWSDP_HOME/apache-ant/bin/ant javadoc

Ant places the output in docs/api.

The PrintOrder Application

PrintOrder unmarshals a UBL order instance, does some simple calculations, and prints a report to the screen. PrintOrder is in the samples.ubl.report package. It imports classes having the following functions.

PrintOrder's main method:

The private methods in PrintOrder use the facade objects to print the data as Strings. For example:

private static void printLetterHead(OrderFacade order) {
    AddressFacade addr = order.getSellerAddress();
    System.out.println("         "
                       + order.getSellerName()
                       + "\n         "
                       + addr.getStreet()
                       + "\n         "
                       + addr.getCity()
                       + ", "
                       + addr.getState()
                       + "  "
                       + addr.getZip());
}

The facade design pattern provides a simpler, higher-level interface. Typically, that's done to isolate an application from the complexity of the underlying subsystems. Here, our principle motivation is to isolate our application from changes to an evolving schema. Since we just wanted to print a simple report, our facades are read-only.

A look at printBuyer() in PrintOrder shows that getting the name of the buyer contact (a person, usually) is just a matter of calling OrderFacade's getBuyerContact() method:

private static void printBuyer(OrderFacade order) {
    AddressFacade addr = order.getBuyerAddress();
    System.out.println("\nSold To: "
                       + order.getBuyerContact()
                       + "\n         c/o "
                       + order.getBuyerName()
                       + "\n         "
                       + addr.getStreet()
                       + "\n         "
                       + addr.getCity()
                       + ", "
                       + addr.getState()
                       + "  "
                       + addr.getZip());
}

getBuyerContact() insulates our application from potential changes in the schema.

public String getBuyerContact() {
    BuyerPartyType party = order.getBuyerParty();
    return ((Name) party.getParty().getPartyName().getName().get(0)).getValue();
}
In this snippet, order is a reference to org.oasis.ubl.order.Order, which is bound to
<element name="Order" type="{urn:oasis:names:tc:ubl:Order:1:0}OrderType"/>
in UBL-Order-1.0.xsd. If that binding were to change, for example, such that order.getBuyerParty() returned, let's say, PartyType, we could make this one-line change to getBuyerContact() without affecting PrintOrder:
PartyType party = order.getBuyerParty();
This pattern characterizes the other methods in OrderFacade and the methods in OrderLineTypeFacade and AddressFacade.

Further Reading

For more information about using JAXB, refer to the Java Web Services Tutorial. For more information about UBL, visit OASIS' Universal Business Language Technical Committee site.