In the world of information technology, more and more corporate enterprises are looking to IT-enable their businesses by providing business services through the internet. In order to gain maximum return on investment from internet business, the industry is rapidly embracing a business-to-business (B2B) oriented transactional paradigm, where services from participating businesses are invoked in order to maximize the automation in a typical business process. An example of this is a supply chain management business process in which a manufacturing business's inventory is closely linked with that of its suppliers.
Over the last few years, XML has emerged as the best form of information exchange in B2B scenarios. Various XML standards have been created for both the horizontal and vertical market sectors and there are ongoing efforts to move towards a standardized format in the various industry sectors.
With the proliferation of XML-based information exchange, the industry is bound to write lots of Java code to consume XML documents. JAXB provides a convenient way to bind an XML schema to a representation in Java code. This makes it easy for you to incorporate XML data and processing functions into applications based on Java technology without having to know much about XML itself.
The purpose of this article is to show developers how to utilize the power, ease and flexibility of JAXB from within WebSphere Studio Application Developer to develop real-world enterprise applications, without having to learn the intricacies of XML parsing techniques.
What you need to know
Although you don't need to worry about XML parsing techniques anymore, you do need to do some reading up! JAXB is built on XML schema. A sound understanding of XML schema is imperative in order to harness the power of JAXB. Business domain objects and their structural relationships can be well-represented through XML schema, provided you have a good understanding of the power of XML schemas. The essence of JAXB lies in its flexible customization of the XML schema for Java objects and its nuances. The JAXB customizations also follow the rules of XML schema. Adding JAXB customizations to a business domain object model, represented in XML schema, is rather simple once the hard work of creating the schema is accomplished.
This article assumes you have an understanding of:
- XML schemas (the more detailed the better)
- Application Developer 5.1
You must have the following products already installed to complete the steps in this article:
- Application Developer 5.1
- Java Web Services Developer's Pack (Java WSDP v1.3)
While most of use are all familiar with Application Developer, the Java WSDP requires a little more of an introduction. The Java Web Services Developer Pack (Java WSDP) from Sun Microsystems is a free integrated toolkit you can use to build, test and deploy XML applications, Web services, and Web applications with the latest Web services technologies and standards implementations. You will need the JAXB compile and runtime libraries included in this package to do the steps in this article. See the Resources section to download the JWSDP.
In object-oriented programming (OO) there are two pivotal concepts: classes and objects. Classes provide the structure for software concepts or entities, whereas objects are live instances of classes. A similar analogy can be used in XML representation. You can think of an XML schema as the allowable structure and constructs that can be used in the creation of an XML document. The schema (in XML) and classes (in OO) are the conceptual building blocks, whereas the documents (in XML) documents and objects (in OO) are live instances that conform to their respective conceptual building blocks.
Working with Java objects and classes is fundamentally different from working with XML. JAXB introduces the idea of data binding to create a correspondence between XML schemas and Java classes. It then uses the mapping to convert XML documents to Java classes and vice versa. The JAXB schema compiler creates Java classes and interfaces based on the structure of the XML schema. JAXB libraries are then used in the process of marshalling and unmarshalling. Marshalling is the process of creating an XML document from one or more Java objects, whereas unmarshalling is the process of creating a Java object from an XML document.
In order to use JAXB in a J2EE or any Java-based application, the first step is to run the JAXB compiler, xjc, that creates the Java classes and interfaces. One or two Java interfaces and corresponding implementation classes are generated for each element definition in the XML schema. The implementation classes are generated in a package separate from the one in which the interfaces are generated. Other than the interfaces and the implementation classes, JAXB-specific classes are generated. These classes are used to perform marshalling and unmarshalling, to create instances of the implementation classes, among other things. Note that the implementation classes are only instantiated through a factory class that is generated by the JAXB compiler. The two most important classes that are used in working with JAXB-created Java objects are:
- Used for marshalling, unmarshalling and validating XML documents
- This is the factory class that is used in order to instantiate the various implementation classes
Setting up the development environment
First, we need to set up our development environment as follows:
- Download the JAXBTestEAR.zip file (see Download section), then extract the contents into C:\temp folder.
- Create a new workspace and import the JAXBTestEAR EAR file. To do this:
- On the C:\ drive, create a folder called JAXB. In that folder, create a folder called workspace.
- Open Application Developer and point the workspace to C:\JAXB\workspace.
- Select File->Import from the Application Developer menu.
- Select EAR file.
- Specify JAXBTestEAR as the project name.
- Browse the file system and select the JAXBTestEAR.ear file.
- Click Finish. The imported project in the J2EE Perspectives Project Navigator tab should look like this:
- Now that we've done the initial setup, we need to set up the JAXB compiler as an External Tool in Application Developer. To do this:
- Select External Tools from the Application Developer menu as show below.
- Click New to create a new configuration.
- On the Main tab, enter the Name, Location, Working Directory and Arguments as shown below. You can browse the file system and workspace to obtain the values shown.
- Switch to the Refresh tab and check the checkboxes as shown below. Highlight the $resource scope variable, and then choose JAXBTest as the specific resource.
- Click Apply to save the configurations.
- Click Run to run the JAXB compiler (xjc.bat) and generate the Java classes and interfaces. The output in the output console will resemble the figure below:
Now we've finished setting up our development environment inside Application Developer.
The example that we're going to develop is a simple graphical user interface (GUI) menuing system. A widget is a conceptual element that defines the whole set of drawing components that constitute a graphical user interface. Examples of widgets are rectangles, squares, circles and any other drawable visual components. Our simple GUI consists of three visual components in the form of rectangles, squares and circles. The Widgets component encapsulates a list of the visual components (rectangles, squares and circles) in any random order. A client can construct the visual components from a given XML document and then retrieve the details of each visual component to be used in any way the client requires.
The rest of this section illustrates and explains the XML schema for the example scenario.
Listing 1. XML Schema for Example Scenario
<?xml version="1.0" encoding="UTF-8> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="1.0" xmlns:domainObjects="http://www.ibm.com/domainobjects" targetNamespace="http://www.ibm.com/domainobjects" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc"> <xsd:annotation> <xsd:appinfo> <jxb:globalBindings collectionType="java.util.ArrayList" fixedAttributeAsConstantProperty="true" generateIsSetMethod="false" enableFailFastCheck="false" choiceContentProperty="false" underscoreBinding="asWordSeparator" typesafeEnumBase="xsd:NCName" typesafeEnumMemberName="generateError" enableJavaNamingConventions="true" bindingStyle="elementBinding"> <xjc:serializable /> <xjc:superClass name="com.ibm.domainobjects.Shape" /> </jxb:globalBindings> <jxb:schemaBindings> <jxb:package name="com.ibm.domainobjects" /> </jxb:schemaBindings> </xsd:appinfo> </xsd:annotation> <xsd:element name="UIWidgets" type="domainObjects:Widgets" /> <xsd:complexType name="Rectangle"> <xsd:attribute name="width" type="xsd:integer"/> <xsd:attribute name="height" type="xsd:integer"/> </xsd:complexType> <xsd:complexType name="Square"> <xsd:attribute name="length" type="xsd:integer"/> </xsd:complexType> <xsd:complexType name="Circle"> <xsd:attribute name="radius" type="xsd:integer"/> </xsd:complexType> <xsd:complexType name="Widgets"> <xsd:choice minOccurs="0" maxOccurs="unbounded"> <xsd:annotation> <xsd:appinfo> <jxb:property name="Widgets" /> </xsd:appinfo> </xsd:annotation> <xsd:element name="rectangle" type="domainObjects:Rectangle" /> <xsd:element name="square" type="domainObjects:Square" /> <xsd:element name="circle" type="domainObjects:Circle" /> </xsd:choice> </xsd:complexType> </xsd:schema>
The xsd:annotation element is a container for xsd:appinfo and xs:documentation elements that contain additional information. These two elements are dedicated to holding machine-processable (xsd:appinfo) information and human readable documentation (xsd:documentation).
The section highlighted in blue denotes the JAXB-specific global customizations of the schema that are applicable to the entire schema file. The section highlighted in red denotes the JAXB-specific customizations that define the package where the generated files are going to be placed; in this case, com.ibm.domainobjects.
In the globalBindings section in blue the collectionType = java.util.ArrayList denotes that any collections that are created inside the Java objects conform to the List interface in Java.
The xjc:serializable element makes sure that all the generated classes are all serializable. This is particularly important when objects are sent and received over the wire while data transfer between various application tiers is performed.
A superClass called Shape is also defined. This denotes that all the elements defined in this schema have a common superclass called Shape. This is shown here in order to illustrate that the classes that are created from the schema can also refer to external classes, which are not created by the JAXB compiler.
The definition of the Widgets element shows that a property called Widgets is defined. Had this property not been defined, the binding compiler would have automatically generated a name for the list of choices (for the rectangles, squares and circles). The auto-generation usually takes the names of the subelements and combines them with an "or." Hence, the accessor name for the list would have been something like:
Obviously the above is not very meaningful. The
jxb:property name="Widgets"denotes that the accessor method will be getWidgets, which is certainly more intuitive than the auto-generated name.
In the example, the JAXBTester class demonstrates:
- How to set up the usage of the external JAXB compiler from Application Developer
- How to use the JAXB compiler to generate Java interfaces and classes
- How to create the Java classes from an XML document
- How to instantiate Java classes, set their attributes and then finally generate its corresponding XML document (Reverse of the previous step)
Various other customizing facets can be used in an XML schema. For detailed specifications for JAXB customizations see Resources.
Using classes generated by the JAXB compiler
You only need to run the JAXB compiler once. There's no need to run it again if the schema is unchanged. However, if the schema undergoes any changes, you'll need to execute the JAXB compiler pre-processing step again in order to regenerate the Java interfaces and classes. In this event, it is advisable to delete all the generated classes from a previous run of the JAXB compiler before running the step once again. This is helpful especially in cases where elements in the schema are deleted. The generated classes from the new run of the compiler do not delete the old generated classes and hence some unused classes from the previous version of the schema will be left behind.
Now that the classes are generated, the fun part begins! It's time to use the generated classes to convert XML documents into Java classes and vice versa. We'll l concentrate on a client class called JAXBTester.
This class demonstrates three activities. It first creates a JAXB context and obtains the necessary handles. It then demonstrates how to use the handles to create the Java object tree from an XML document. It also shows how the various Java objects can be instantiated, their attributes set, and then finally how they can use the necessary handles to generate an XML representation of the Java object tree.
Analysis of JAXBTester
JAXBTester has three methods, as described here:
- The createContext method essentially creates an instance of the JAXBContext class from which we can get a handle to an instance of the Unmarshaller and Marshaller instances.
- This method accepts an XML document--in our case, the schema.xml file found in the schema folder under WebContent. It first creates an instance of the UIWidgets class (the root element in the XML document). It then invokes the getWidgets accessor method on the UIWidgets instance, and iterates through the list of contained widgets, retrieving the various widget-specific attributes in each iteration.
- This method illustrates how to instantiate any element in the XML schema for which there are generated Java objects, set the various attribute values, and then add each object to its container. An instance of ObjectFactory is used to create the various instances of the Java objects; for example RectangleImpl, CircleImpl, and so on. The getWidgets method on the instance of UIWidgetsImpl returns a handle to an instance of a live List to which the child elements (instances of RectangleImpl, SquareImpl and CircleImpl) can be added. Once the object structure is created, a single method call on the instance of the Marshaller generates the XML representation of the object structure.
Notice how you don't need to code a single line of XML code! The specifics of the conversion are all contained inside the generated classes.
Running the sample
Before running the client class, we must do the following steps:
- Run the JAXB compiler to generate the Java object tree
- Uncomment the import statements that are commented out in the JAXBTester. Also, before compiling JAXBTester, uncomment the method bodies of unmarshallIt and marshallIt that are commented out. These sections are commented out because the classes that are referenced in the import statements> and the methods are all from the generated classes. The EAR file, when imported, did not have these generated classes. Therefore, prior to step 1, JAXBTester would not have compiled.
- If necessary, change the value of the absPathToXML that denotes the path where the schema.xml file resides to reflect the path to the file in the file system
Now you're all set to run the sample and see the results for yourself.
This article introduced us to the basics of JAXB. It demonstrated how you can use JAXB in Application Developer to create a J2EE application without having to understand XML parsing.
The best way to learn JAXB is to first get very familiar and comfortable with XML schema and then learn the tricks of JAXB customizations. And the best way to learn XML schema is to pick up a book, read it, and then apply the concepts in real-world scenarios, exploiting the various features. The O'Reilly book XML Schema is my favorite.
|Code sample||JAXBTestEAR.zip ( HTTP | FTP )||3.5 MB|
- Java Web Services Developer Pack 1.3 is the services pack for the JAXB compiler. JDK 1.4 is required.
- Data Binding with JAXB defines the entire JAXB specification.
- Customizing JAXB Schemas is an excellent article on to use JAXB specifications to customize an XML schema for an application.
- Technical Article on JAXB provides an excellent description of how JAXB works.
- XML Schema (O'Reilly & Associates; 2002), by Eric van der Vlist explains XML Schema foundations, different styles for writing schemas, design choices, best practices, and much more.