Using JAXB to generate XML from the Java, XSD

We can use JAXB to marshal the Java objects into XML using the given Schema and vice versa- unmarshal XML into Java objects. The xml schema can be specified in DTD, XSD or other format. The tool “xjc” is used to generate the annotated Java classes from the XSD schema. One can download the Java WSDP from here, it includes the JAXB implementation tools required. Here I will throw light on how to generate XML dynamically. Even I havent gone in depth with JAXB, but I found this really useful and thought of sharing it in the blog.

The sample XSD being used is: expense.xsd

<?xml version="1.0"?></div>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="expenseReport" type="ExpenseT" />
<xs:complexType name="ExpenseT">
    <xs:sequence>
        <xs:element name="user" type="UserT"/>
        <xs:element name="items" type="ItemListT"/>
    </xs:sequence>
</xs:complexType>

<xs:complexType name="UserT">
    <xs:sequence>
        <xs:element name="userName" type="xs:string" />
    </xs:sequence>
</xs:complexType>
<xs:complexType name="ItemListT">
     <xs:sequence>
         <xs:element name="item" type="ItemT" maxOccurs="unbounded"/>
     </xs:sequence>
</xs:complexType>
<xs:complexType name="ItemT">
     <xs:sequence>
         <xs:element name="itemName" type="xs:string" />
         <xs:element name="purchasedOn" type="xs:string" />
         <xs:element name="amount" type="xs:decimal" />
     </xs:sequence>
</xs:complexType>
</xs:schema>

You can read about XSD here.

Now we use the xjc tool to generate corresponding Java classes. The generate java classes are annotated appropriately. Am not going into the annotation of the classes, cause it would make things complicated.

xjc.exe expense.xsd

By default the command generates the Java classes in a directory named “generated”. There are lot of options which can be used with xjc and one can have a look at using- xjc -help.

The below Main class- Main.java uses the generated classes for creating the XML.


package generated;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.math.BigDecimal;

public class Main

{
    public static void main(String[] args) throws JAXBException
    {

        ObjectFactory factory = new ObjectFactory();

        UserT user = factory.createUserT();
        user.setUserName("Sanaulla");
        ItemT item = factory.createItemT();
        item.setItemName("Seagate External HDD");
        item.setPurchasedOn("August 24, 2010");
        item.setAmount(new BigDecimal("6776.5"));

        ItemListT itemList = factory.createItemListT();
        itemList.getItem().add(item);

        ExpenseT expense = factory.createExpenseT();
        expense.setUser(user);
        expense.setItems(itemList);

        JAXBContext context = JAXBContext.newInstance("generated");
        JAXBElement<ExpenseT> element = factory.createExpenseReport(expense);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE);
        marshaller.marshal(element,System.out);
    }

}

In the above XSD, we see that there are few complex types declared. These complex types generate in to Java classes. The child elements and attributes become the properties of the class and they are provided with the getters and setters. One cannot directly create the instance of such classes i.e cannot call new on them. When ever we compile a XSD, there is a ObjectFacotry class generated- this is the factory for creating the instances of the XSD Complex types (Lines-17,19, 24, 27 in the above Java class). Once we get the instance we populate the properties with corresponding data using the setters provided with the class. Also note that- A complex element can have many complex elements as the members of the class. In that case what happens we use the factory to get the instance of the complex elements and then use the setters of the outer complex element. For example: In the above XSD- ExpenseT is a complex type which consists of UserT and a list of ItemT (ItemListT). In the above Java class- Lines-27,28,29- am creating an instance of ExpenseT and then using the setters to set the values of the UserT and ItemListT. The RootElement- is created by calling createExpenseReport() for the factory. The name of the method is influenced by the name of the root element and the return type and the argument type of the method is same as that of the type of root element.

Once we have set the values for the different elements, attributes which are to go into the XML, its now time to actually generate the XML. We must have an Marshaller (To get XML from the Java objects) or an Unmarshaller (to get java objects from XML). We would need a Marshaller- which can be obtained from the JAXBContext instance. Lines- 31,32 obtain an instance of Marshaller. Different properties can be set for the marshaller and in the above code we are setting the jaxb.formatted.output as true- which means that the xml obtained is neatly formatted making is readable to the user.

Different properties supported are:

  • jaxb.encoding
  • jaxb.formatted.output
  • jaxb.schemaLocation
  • jaxb.noNamespaceSchemaLocation
  • jaxb.fragment

.marshal() is the method used to generate the XML. Its is overloaded to accept the following output mechanisms:

  • org.xml.sax.ContentHandler
  • org.w3c.dom.Node
  • javax.xml.transform.Result
  • java.io.Writer
  • java.io.OutputStream
  • javax.xml.stream.XMLStreamWriter
  • javax.xml.stream.XMLEventWriter

The xml generated is shown below:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <expenseReport>
    <user>
      <userName>Sanaulla</userName>
   </user>
   <items>
     <item>
       <itemName>Seagate External HDD</itemName>
       <purchasedOn>August 24, 2010</purchasedOn>
       <amount>6776.5</amount>
     </item>
   </items>
</expenseReport>

PS: I havent gone much into the details of JAXB. This is just the overview of how one can generate XML confirming to the schema.

Read about How to Unmarshall the XML data.



Categories: Java

Tags: , , ,

26 replies

  1. When I unmarshall xml, I am not able to find expenseReport object.
    Can you post unmarshall code also?

    Like

  2. Hi Mohamed,

    Nice post. I noticed your information as to where to obtain a JAXB implementation is out date. Since Java SE 6 an implementation of JAXB has been included in the JRE/JDK. Also since JAXB is a specification (JSR-222), there are several implementations available:

    Metro JAXB
    EclipseLink JAXB (MOXy)
    Apache JaxMe

    -Blaise

    Like

  3. JAXBElement element = factory.createExpenseReport(expense);

    This function is not available with argument.
    It is available with 0 arguments and moreover the return type doesn’t match.
    Class casting doesn’t help.

    Please help me…

    Like

  4. your code is not good..
    plz improve..

    Like

  5. Thanks for the post. It can be done from eclipse also. Right click the xsd > source > generate > xml > select root > finish.

    Like

  6. Nice post!

    Can you specify out if the code in Main method is thread-safe?

    Thanks!

    Like

  7. Thanks , this post helped me a lot as i had a similar requirement to create xml string using xsd .

    Like

  8. hi can you please tell me how to partially unmarshal using jaxb

    Like

  9. Hi Mohamed I got the exception at line number 31 in your application,
    javax.xml.bind.annotation.XmlAccessorType.value()Ljavax/xml/bind/annotation/AccessType;

    Like

  10. can you tell me the why it’s happened.

    Like

  11. It’s resolved,problem with jars.Thanks for the reply

    Like

  12. Thanks. It helped me.

    Like

  13. How can i delete datas in the xml file?

    Like

  14. Hi, What is ObjectFactory here? which package we have to import for this one

    Like

  15. I am using JAXB for creating SOAP Webservices. my SOAP request and SOAP response working in tomcat but it is not wotking in JBoss-5.0.2 . below is my Marshller code.

    messageFactory = MessageFactory.newInstance();
    soapMessage = messageFactory.createMessage();
    soapBody = soapMessage.getSOAPBody();
    logger.info(“soapBody==>”+ soapBody);
    jAXBContext = JAXBContext.newInstance(loginMessage.getClass());
    marshaller = jAXBContext.createMarshaller();
    marshaller.marshal(loginMessage, soapBody);
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    soapMessage.saveChanges();
    outputStream = new ByteArrayOutputStream();
    soapMessage.writeTo(outputStream);
    rawRequest = new String(outputStream.toByteArray(), UTF_8);
    requestFormate = new RequestFormate();
    outputStream.close();
    formatedLoginRequest = requestFormate.getXmlFormate(rawRequest);

    Every things working in the tomcat but in JBoss it is not working.

    any body can help me?

    thanks in advance.

    Like

    • hi mohamed,
      i have tried that segregates elements or nested element using JAXB . But could not. i got converted from java objects into XML but not segregates. And i had used annotation like @XmlRootElement(name = “Report”) and @XmlElement(name = “custName”) for marshalling .. i need help from u regarding how to segregates elements

      Like

  16. Nice

    Like

  17. javax.xml.bind.MarshalException
    – with linked exception:
    [Exception [EclipseLink-25007] (Eclipse Persistence Services – 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.XMLMarshalException
    Exception Description: A descriptor for class com.candelalabs.Lg.generatedJava.ObjectFactory was not found in the project. For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.]
    at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:686)
    at com.candelalabs.Lg.xmlString.JavaXmlString.jaxbObjectToXML(JavaXmlString.java:34)
    at com.candelalabs.Lg.xmlString.JavaXmlString.main(JavaXmlString.java:19)
    Caused by: Exception [EclipseLink-25007] (Eclipse Persistence Services – 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.XMLMarshalException
    Exception Description: A descriptor for class com.candelalabs.Lg.generatedJava.ObjectFactory was not found in the project. For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
    at org.eclipse.persistence.exceptions.XMLMarshalException.descriptorNotFoundInProject(XMLMarshalException.java:140)
    at org.eclipse.persistence.internal.oxm.Context$ContextState.getSession(Context.java:145)
    at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:795)
    at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:1)
    at org.eclipse.persistence.internal.oxm.Context.getSession(Context.java:466)
    at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:364)
    at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:1)
    at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshalStreamOrWriter(XMLMarshaller.java:1123)
    at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:1079)
    at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:1034)
    at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:684)
    … 2 more

    please help

    Like

  18. For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.]

    Like

Trackbacks

  1. creating a .xml file from .xsd with java | Jisku.com
  2. Using JAXB to generate Java Objects from XML document | Experiences Unlimited

Leave a Reply to Jacob Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: