Monday, 21 March 2011

Jaxb : Shortcomings of API


JAXB has some shortcomings. Client apps can't customize the marshalling behavior very much. The only standard options are (1) setting the encoding to be used, (2) turn on/off indentation, and (3) add xsi:schemaLocation/xsi:noNamespaceSchemaLocation. You can't even specify how a document should be indented. While you can always plug in some other XML writer, it's not as easy as the rest of JAXB. It would have been easier if Java had a reusable XML writer, like the one in Microsoft .NET. Then the JAXB API could have been designed to work with it.
Further, the ValidationEventHandler interface handles errors during unmarshalling, validation, and marshalling, and ValidationEvent objects represent error information. The problem is that you can't throw ValidationEvent, because it's not throwable. If you compare this with SAX, where you often throw SAXParseException from your ErrorHandler, this is a big difference. I don't claim that the SAX's way is better, but you have to learn yet another way of handling errors.

Jaxb : Validation


JAXB also has the capability to validate an object graph in memory without actually writing it to XML. This allows client apps to check if a graph is okay and ready to process; if not, validation will identify objects that contain errors so that, for example, client apps can ask users to fix those.
The following code validates the object "o".
Validator v = context.createValidator();
if(!v.validate(o)) System.err.println("error");
To receive detailed information about errors, you need to register ValidationEventHandler with the Validator, just like you did in Unmarshaller and Marshaller. This is analogous to registering an ErrorHandler for a SAX parser.
You can also first marshal an object graph and then validate XML (for example by Java API for validators). But doing so makes it much harder to associate errors with their sources, which makes debugging harder for humans. Validation after marshalling will give you errors like "missing <foo> element," but you can hardly know what is actually wrong in the object graph.
Validity is not enforced while you are modifying an object graph; you always have to explicitly validate it. To edit a valid object graph into another valid object graph, you may need to go through invalid intermediate states. If validity is enforced on every step of mutation, this becomes impossible.

Marshalling : Jaxb


A Marshaller is used to write an object graph into XML. To write an object o to a file, you would do
Marshaller marshaller = context.createMarshaller();
marshaller.marshal( o, new FileOutputStream("foo.xml") );
There are other overloaded versions which allow you to produce XML as a a DOM tree or as SAX events. For example, by using StringWriter, you can marshal an object into a string. You can also marshal an object graph to a javax.xml.transform.Result object.
In the previous version of JAXB, this functionality was provided as a method on the generated class, and the number of formats was limited. Making it a separate interface enables mapping of existing classes to XML in the future.
In the previous version of JAXB, there was no provision for controlling the formatting. In the new API, you can control the behavior of marshalling by setting Marshaller properties. For example, you can toggle indentation of the XML. More importantly, the mechanism is extensible, which means JAXB providers can expose advanced features.
Although you can customize the behavior of marshalling to some degree by using this mechanism, there's a good chance it doesn't fill your needs completely. For example, some people might want to use tabs for indentation and others might prefer spaces. In some schemas, certain elements cannot be indented without changing the meaning. You might want to control the namespace prefixes. Or you might want to add a processing instruction to the document. In addition, relying on vendor-specific properties compromises portability.
The new version of JAXB can produce XML as SAX events. That is, you can pass ContentHandler and have it receive SAX events from a JAXB object. This gives client apps plenty of chances to modify XML. For example, you can add and remove elements or attributes, use one of the freely available serializers ( XMLWriter by David Megginson, org.apache.xml.serialize.XMLSerializer) for better output, or write your own XML serializer that prints XML in your preferred way.
Finally, you can ask a Marshaller to marshal an invalid object graph by setting a ValidationEventHandler. If a provider supports error recovery, you can tell it to write XML even if it's incomplete.

UnMarshalling : Jaxb


An unmarshaller is used to read XML and build an object tree from classes generated by the compiler. To read an XML file, you would simply do
Unmarshaller unmarshaller = context.createUnmarshaller();
MyObject o = (MyObject)unmarshaller.unmarshal(new File("foo.xml"));
There are other overloaded versions that take different types of input, such as InputStream or InputSource. You can even unmarshal a javax.xml.transform.Source object. All in all, it's similar to the way DOM trees are parsed.
In the previous version of JAXB, this functionality was provided as a method on the generated class. Since one cannot add methods to existing classes, this design made it impossible to unmarshal them. By moving it into a separate Unmarshaller interface, the new API makes it possible to support this in a future version.
JAXB also supports unmarshalling via a SAX ContentHandler. You can send SAX events to the unmarshaller and have it unmarshal objects. This enhances the connectivity of the Unmarshaller considerably. For example, you can parse the header of a message by using JAXB and send the body of the message to another component. With ContentHandler support, this can be done efficiently.
By default, Unmarshaller is very forgiving. Even if a document is invalid, it tries to recover from errors. If the document is so broken that it cannot be read, an UnmarshalException will be thrown.
It's often desirable to get more information about errors or reject documents with errors. The first step to do this is to set ValidationEventHandler to the Unmarshaller. A ValidationEventHandler can explicitly tell a JAXB implementation whether it should reject a document or try to recover from errors. It also gives you more information, such as line numbers, about errors.
An Unmarshaller can validate a document with the schema while unmarshalling. With this option turned on, it rejects anything short of a valid document. However, W3C XML Schema validation can be very costly.
Another possibility is to set up a SAX pipeline in such a way that your XML parser does the validation; alternately, you could install a stand-alone validator in the pipeline (such as JARV: validation API). In this way, for example, you can change your schema to change what you get from the compiler, while maintaining the scrutiny of the original schema.

Jaxb : TABLE OF CONTENTS

Jaxb : Binding XML Schemas


This section describes the default XML-to-Java bindings used by JAXB. All of these bindings can be overridden on global or case-by-case levels by means of a custom binding declaration.

Simple Type Definitions

A schema component using a simple type definition typically binds to a Java property. Since there are different kinds of such schema components, the following Java property attributes (common to the schema components) include:
  • Base type
  • Collection type, if any
  • Predicate
The rest of the java property attributes are specified in schema component using simple type definition.

Default Data Type Bindings


The Java language provides a richer set of data type than XML schema.
XML Schema TypeJava Data Type
xsd:stringjava.lang.String
xsd:integerjava.math.BigInteger
xsd:intint
xsd.longlong
xsd:shortshort
xsd:decimaljava.math.BigDecimal
xsd:floatfloat
xsd:doubledouble
xsd:booleanboolean
xsd:bytebyte
xsd:QNamejavax.xml.namespace.QName
xsd:dateTimejava.util.Calendar
xsd:base64Binarybyte[]
xsd:hexBinarybyte[]
xsd:unsignedIntlong
xsd:unsignedShortint
xsd:unsignedByteshort
xsd:timejava.util.Calendar
xsd:datejava.util.Calendar
xsd:anySimpleTypejava.lang.String


Default Binding Rules


The JAXB binding model follows the default binding rules summarized below:
FromTo
XML Namespace URIJava package
Named complex typeJava content interface
Anonymous inlined type definition of an element declarationJava content interface
A named simple type definition with a basetype that derives from "xsd:NCName" and has enumeration facetenum class
A global element declaration to a Element interfaceJava Element interface
Local element declaration that can be inserted into a general content listJava Element interface
AttributeJava property

Prerequisites for jaxb

  • Download and install the Java Web Services Developer Pack (Java WSDP) currently at version 2.0 from Sun Microsystem. The Java WSDP is a free, integrated toolkit that allows Java developers to build, test, and deploy XML applications, Web services, and Web applications. Assume that you install JWSDP to C:\jwsdp-2.0 directory.
  • Create a C:\jaxb_samples directory on your machine.
  • For occasional developers, it is convenient to set these variables in a batch file that you run every time you open a command-prompt window. Alternatively, these settings can be permanently added to the command-prompt shortcut. Here is what you should add to a “jaxbsetup.bat” file in C:\jaxb_samples directory (note that only “set” commands are in this listing, any line that doesn’t start with “set” is a continuation of the previous line): set JWSDP_HOME=C:\jwsdp-2.0
    set JWSDP_JAXB_LIB=%JWSDP_HOME%\jaxb\lib
    set JWSDP_SHARED_LIB=%JWSDP_HOME%\jwsdp-shared\lib
    set JWSDP_SJSXP_LIB=%JWSDP_HOME%\sjsxp\lib
    set CLASSPATH=%JWSDP_JAXB_LIB%\jaxb-api.jar;
                  %JWSDP_JAXB_LIB%\jaxb-impl.jar;
                  %JWSDP_JAXB_LIB%\jaxb1-impl.jar;
                  %JWSDP_JAXB_LIB%\jaxb-xjc.jar;%CLASSPATH%
    set CLASSPATH=%JWSDP_SJSXP_LIB%\sjsxp.jar;
                  %JWSDP_SJSXP_LIB%\jsr173_api.jar;%CLASSPATH%
    set CLASSPATH=%JWSDP_SHARED_LIB%\activation.jar;
                  %JWSDP_SHARED_LIB%\resolver.jar;%CLASSPATH%
    set PATH=
    %JWSDP_HOME%\jaxb\bin;%JWSDP_HOME%\jwsdp-shared\bin;%PATH%
  • Copy %JWSDP_HOME%\jaxb\samples\create-marshal directory to jaxb_smaple directory. (Note: we  will not use ant to build this project in here. You can delete build.xml file).

  • Create a subdirectory called classes under jaxb_sample\create-marshal.
Case when JWSDB doesn't get installed 
In this case first try to trouble shoot why it is not getting installed. Because it installs all the necessary jars into JDK like jaxb, saaj, jaxp,jaxrc, etc.

But if not then download jaxb from here. And then add this jar to Eclipse project as external jar.