October 6, 2010

How Does JAXB Compare to XStream?

The XStream FAQ states the following when being compared to JAXB:

JAXB is a Java binding tool. It generates Java code from a schema and you are able to transform from those classes into XML matching the processed schema and back. Note, that you cannot use your own objects, you have to use what is generated.
In this post I will provide an alternative answer to that question.


Java Model

We will use the following model for this example.  The classes represent customer data.  The get/set methods have been omitted to save space.

package comparison;

import java.util.ArrayList;
import java.util.List;

public class Customer {

    private long id;
    private String name;
    private Address address;
    private List<phonenumber> phoneNumbers;

    public Customer() {
        phoneNumbers = new ArrayList<PhoneNumber>();
    }

}

package comparison;

public class Address {

    private String city;
    private String street;

}

package comparison;

public class PhoneNumber {

    private String type;
    private String number;

}

Customer Data

The following instance of Customer will be marshalled to XML using both JAXB and XStream.

package comparison;

public class Data {

    public static Customer CUSTOMER;

    static {
        CUSTOMER = new Customer();
        CUSTOMER.setId(123);
        CUSTOMER.setName("Jane Doe");

        Address address = new Address();
        address.setStreet("1 A Street");
        address.setCity("Any Town");
        CUSTOMER.setAddress(address);

        PhoneNumber workPhoneNumber = new PhoneNumber();
        workPhoneNumber.setType("work");
        workPhoneNumber.setNumber("555-WORK");
        CUSTOMER.getPhoneNumbers().add(workPhoneNumber);

        PhoneNumber cellPhoneNumber = new PhoneNumber();
        cellPhoneNumber.setType("cell");
        cellPhoneNumber.setNumber("555-CELL");
        CUSTOMER.getPhoneNumbers().add(cellPhoneNumber);
    }

}

Marshal Code

This is the code we will use to convert the objects to XML.

XStream

The following code will be used to marshal the instance of Customer to an OutputStream.  The XStream code is quite compact.

package comparison.xstream;

import com.thoughtworks.xstream.XStream;

import static comparison.Data.CUSTOMER;

public class XStreamDemo {

    public static void main(String[] args) {
        XStream xstream = new XStream();
        xstream.autodetectAnnotations(true);
        xstream.toXML(CUSTOMER, System.out);
    }
}

JAXB

The following code will be used to marshal the instance of Customer to an OutputStream.  A couple of differences are already apparent:
  1. A JAXBContext needs to be initialized on the binding metadata before the marshal operation can occur.
  2. Unlike XStream JAXB does not format the XML by default, so we will enable this feature.
  3. With no metadata specified we need to supply JAXB with a root element name (and namespace).
package comparison.jaxb;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
import comparison.Customer;

import static comparison.Data.CUSTOMER;

public class JAXBDemo {

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

        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        JAXBElement<Customer> jaxbElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, CUSTOMER);
        marshaller.marshal(jaxbElement, System.out);
    }
}

Default XML Output

First we will examine the XML output produced by both XStream and JAXB if no metadata is used to customize the output.

XStream

XStream will produce the following XML.  Note some of the elements are named after the fully qualified class name.
<comparison.Customer>
    <id>123</id>
    <name>Jane Doe</name>
    <address>
        <city>Any Town</city>
        <street>1 A Street</street>
    </address>
    <phoneNumbers>
        <comparison.PhoneNumber>
            <type>work</type>
            <number>555-WORK</number>
        </comparison.PhoneNumber>
        <comparison.PhoneNumber>
            <type>cell</type>
            <number>555-CELL</number>
        </comparison.PhoneNumber>
    </phoneNumbers>
</comparison.Customer>

JAXB

JAXB produces the following XML.  The representation is straight forward and more compact than the XStream representation.

<customer>
    <id>123</id>
    <address>
        <city>Any Town</city>
        <street>1 A Street</street>
    </address>
    <name>Jane Doe</name>
    <phoneNumbers>
        <number>555-WORK</number>
        <type>work</type>
    </phoneNumbers>
    <phoneNumbers>
        <number>555-CELL</number>
        <type>cell</type>
    </phoneNumbers>
</customer>

Field Access

For this example we will configure our XML binding tools to interact directly with the fields (instance variables).

XStream

XStream uses field access by default.

JAXB

By default JAXB will access public fields and properties.  We can configure JAXB to use field access with the following package level annotation:

@XmlAccessorType(XmlAccessType.FIELD)
package comparison;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

Renaming Elements

Next we will look at how to tweak the XML output using the appropriate mapping metadata.  First we will rename some elements.  As you will see the amount of configuration required is almost identical.

XStream

For XStream we will use @XStreamAlias to configure the root element, and @XStreamImplicit to configure the phoneNumbers property.

import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;

@XStreamAlias("customer")
public class Customer {

    private long id;
    private String name;
    private Address address;

    @XStreamImplicit(itemFieldName="phone-number")
    private List phoneNumbers;

    public Customer() {
        phoneNumbers = new ArrayList();
    }

}

JAXB

For JAXB we will use @XmlRootElement to configure the root element, and @XmlElement to configure the phoneNumbers property.
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer {

    private long id;
    private String name;
    private Address address;

    @XmlElement(name="phone-number")
    private List phoneNumbers;

    public Customer() {
        phoneNumbers = new ArrayList();
    }

}

Note:  The JAXB Marshal code can now be simplified since we no longer need to supply the root element information:

package comparison.jaxb;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import comparison.Customer;

import static comparison.Data.CUSTOMER;

public class JAXBDemo {

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

        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(CUSTOMER, System.out);
    }
}

XML Output

At this point the same XML is being produced by XStream and JAXB.

<customer>
    <id>123</id>
    <name>Jane Doe</name>
    <address>
        <city>Any Town</city>
        <street>1 A Street</street>
    </address>
    <phone-number>
        <type>work</type>
        <number>555-WORK</number>
    </phone-number>
    <phone-number>
        <type>cell</type>
        <number>555-CELL</number>
    </phone-number>
</customer>

Change the Order of Elements

We will tweak the document again to make sure that when marshalling an Address object the "street" element will always appear before the "city" element.

XStream

For XStream we will need to change our marshal code.  The following is based on instructions given in the XStream FAQ:

package comparison.xstream;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.FieldDictionary;
import com.thoughtworks.xstream.converters.reflection.SortableFieldKeySorter;
import com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider;

import comparison.Address;

import static comparison.Data.CUSTOMER;

public class XStreamDemo {

    public static void main(String[] args) {
        SortableFieldKeySorter sorter = new SortableFieldKeySorter();
        sorter.registerFieldOrder(Address.class, new String[] { "street", "city"});
        FieldDictionary fieldDictionary = new FieldDictionary(sorter);
        Sun14ReflectionProvider reflectionProvider = new Sun14ReflectionProvider(fieldDictionary);

        XStream xstream = new XStream(reflectionProvider);

        xstream.autodetectAnnotations(true);

        xstream.toXML(CUSTOMER, System.out);
    }

}

JAXB

For JAXB we can configure the ordering of elements right on the model class.  We will use @XmlType to do this.

package comparison;

import javax.xml.bind.annotation.XmlType;

@XmlType(propOrder={"street", "city"})
public class Address {

    private String city;
    private String street;

}

XML Output

The XML output is the same for both JAXB and XStream.
<customer>
    <id>123</id>
    <name>Jane Doe</name>
    <address>
        <street>1 A Street</street>
        <city>Any Town</city>
    </address>
    <phone-number>
        <type>work</type>
        <number>555-WORK</number>
    </phone-number>
    <phone-number>
        <type>cell</type>
        <number>555-CELL</number>
    </phone-number>
</customer>

Mapping to an Attribute

Now we will look at how to tweak the XML output using the appropriate mapping metadata to produce XML attributes.  As you will see the amount of configuration required is almost identical.

XStream

For XStream we will use @XStreamAsAttribute to configure the id property to be represented as an XML attribute.

package comparison;

import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamImplicit;

@XStreamAlias("customer")
public class Customer {

    @XStreamAsAttribute
    private long id;

    private String name;
    private Address address;

    @XStreamImplicit(itemFieldName="phone-number")
    private List phoneNumbers;

    public Customer() {
        phoneNumbers = new ArrayList();
    }

}

JAXB

For JAXB we will use @XmlAttribute to configure the id property to be represented as an XML attribute.
package comparison;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer {

    @XmlAttribute
    private long id;

    private String name;
    private Address address;

    @XmlElement(name="phone-number")
    private List phoneNumbers;

    public Customer() {
        phoneNumbers = new ArrayList();
    }

}

XML Output

The XML output is the same for both JAXB and XStream.
<customer id="123">
    <name>Jane Doe</name>
    <address>
        <city>Any Town</city>
        <street>1 A Street</street>
    </address>
    <phone-number>
        <type>work</type>
        <number>555-WORK</number>
    </phone-number>
    <phone-number>
        <type>cell</type>
        <number>555-CELL</number>
    </phone-number>
</customer>

Mapping Objects to Simple Content

To compact our document even further we will map the PhoneNumber class to a complex type with simple content.

XStream

With XStream we can do this using a converter.  Examples of creating converters can be found on the XStream website:
We can reference the converter on the phoneNumbers property using @XStreamConverter.

package comparison;

import java.util.ArrayList;
import java.util.List;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamImplicit;

@XStreamAlias("customer")
public class Customer {

    @XmlAttribute
    private long id;

    private String name;
    private Address address;

    @XStreamImplicit(itemFieldName="phone-number")
    @XStreamConverter(PhoneNumberConverter.class)
    private List phoneNumbers;

    public Customer() {
        phoneNumbers = new ArrayList();
    }

}

The converter can be implemented as follows:

package comparison;

import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

public class PhoneNumberConverter implements Converter {

    public boolean canConvert(Class clazz) {
        return PhoneNumber.class == clazz;
    }

    public void marshal(Object object, HierarchicalStreamWriter hsw, MarshallingContext mc) {
        PhoneNumber phoneNumber = (PhoneNumber) object;
        hsw.addAttribute("type", phoneNumber.getType());
        hsw.setValue(phoneNumber.getNumber());
    }

    public Object unmarshal(HierarchicalStreamReader hsr, UnmarshallingContext uc) {
        PhoneNumber phoneNumber = new PhoneNumber();
        phoneNumber.setType(hsr.getAttribute("type"));
        phoneNumber.setNumber(hsr.getValue());
        return phoneNumber;
    }

}

JAXB

For JAXB we will use the @XmlAttribute and @XmlValue annotations on the PhoneNumber class.

package comparison;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;

public class PhoneNumber {

    @XmlAttribute
    private String type;

    @XmlValue
    private String number;

}

XML Output:

The XML output is the same for both JAXB and XStream.

<customer id="123">
    <name>Jane Doe</name>
    <address>
        <street>1 A Street</street>
        <city>Any Town</city>
    </address>
    <phone-number type="work">555-WORK</phone-number>
    <phone-number type="cell">555-CELL</phone-number>
</customer>

Applying Namespaces

We will now namespace qualify the XML document.

XStream

Namespace support in XStream appears to be limited to the StaxDriver.  For more information see:
package comparison.xstream;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.FieldDictionary;
import com.thoughtworks.xstream.converters.reflection.SortableFieldKeySorter;
import com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider;
import com.thoughtworks.xstream.io.xml.QNameMap;
import com.thoughtworks.xstream.io.xml.StaxDriver;

import comparison.Address;

import static comparison.Data.CUSTOMER;

public class XStreamDemo {

    public static void main(String[] args) {
        QNameMap nsm = new QNameMap();
        nsm.setDefaultNamespace("http://www.example.com");
        StaxDriver staxDriver = new StaxDriver(nsm);

        SortableFieldKeySorter sorter = new SortableFieldKeySorter();
        sorter.registerFieldOrder(Address.class, new String[] { "street", "city"});
        FieldDictionary fieldDictionary = new FieldDictionary(sorter);
        Sun14ReflectionProvider reflectionProvider = new Sun14ReflectionProvider(fieldDictionary);

        XStream xstream = new XStream(reflectionProvider, staxDriver);

        xstream.autodetectAnnotations(true);

        xstream.toXML(CUSTOMER, System.out);
    }

}

Note: With this change I lost XML formatting, the following was produced.

<customer xmlns="http://www.example.com" id="123"><name>Jane Doe</name><address><street>1 A Street</street><city>Any Town</city></address><phone-number type="work">555-WORK</phone-number><phone-number type="cell">555-CELL</phone-number></customer>
 

JAXB

We can configure the namespace information using the @XmlSchema package level annotation:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlSchema(namespace="http://www.example.com", 
           elementFormDefault=XmlNsForm.QUALIFIED)
package comparison;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

The following XML was produced

<customer xmlns="http://www.example.com" id="123">
    <name>Jane Doe</name>
    <address>
        <street>1 A Street</street>
        <city>Any Town</city>
    </address>
    <phone-number type="work">555-WORK</phone-number>
    <phone-number type="cell">555-CELL</phone-number>
</customer>
Summary

As can be seen from this example JAXB compares very well to XStream.

34 comments:

  1. Blaise,

    thanks for this comprehensive summary, really great.

    One addition where I personally found JAXB to be superior to xstream is when you apply model transformations (as opposed to simple type conversions).

    I think that JAXB's XmlAdapter is much simpler to deal with than xstream's custom mappers. I often see XSLT being used with xstream instead, but than you're using an additional language (and one which many java developers find cumbersome).

    Thanks again,
    Wolfgang

    ReplyDelete
  2. Wolfgang,

    I agree on XmlAdapter, it is my favourite JAXB feature. It was actually the topic of my first blog post XmlAdapter - JAXB's Secret Weapon.

    -Blaise

    ReplyDelete
  3. Excellent post, also note that JAXB now comes bundled on JDK, so the use of XStream gets a bit unneeded if the xml to be marshaled/unmarshaled are simple enough

    ReplyDelete
  4. sombriks,

    In this example JAXB handled the XML better than XStream. This was especially true WRT namespace handling. For more information on JAXB's namespace support see:

    - JAXB & Namespaces

    XStream does have the converter concept, but JAXB has the much more powerful XmlAdapter feature:

    - XmlAdapter - JAXB's Secret Weapon

    Plus since JAXB is a spec, individual implementations can offer their own extensions such as MOXy's XPath based mapping:

    - XPath Based Mapping
    - XPath Based Mapping - Geocode Example

    JAXB is not only a standard part of Java SE 6, but the default binding layer for two Java EE Web Service standards JAX-WS & JAX-RS. JAXB is the enterprise Java binding layer.

    -Blaise

    ReplyDelete
  5. Blaise,

    I guess the XStream FAQ primarily just needs an update for JAXB 2.0 ;-)

    My experience with XStream is that it's great for serializing/deserializing arbitrary object graphs, but it's very hard to make the xml comply to some given schema. JAXB is at times more heavy-weight, but much more powerful as well.

    But both by 95% serve the same purpose. I even started a little adapter class that uses XStream as an JAXB implementation... it's yet not much more than a proof of concept, though:

    https://messageapi.dev.java.net/source/browse/messageapi/trunk/adapter/src/main/java/com/oneandone/consumer/messageapi/xstream

    One thing that annoys me, though, is that the JDK "reference implementation" does not seem to comply to the standard paragraph 8.5.4, which says that Maps have to be supported. MOXy does, but the RI does not... or am I getting something wrong?


    -Rüdiger

    ReplyDelete
  6. Rüdiger,

    The XStream FAQ definitely needs to be updated for JAXB 2.0 :).

    To be fair XStream has times when it is more heavy weight. This can be seen in this post:
    - A field dictionary had to be created to control the order of elements.
    - A converter need to be created to map an object to simple content.
    - The driver had to be changed to apply namespaces.

    WRT 95%:
    - XStream cannot generate classes from XML Schema. There FAQ recommends using XMLBeans for this purpose.
    - XStream cannot generate an XML schema from Java classes
    - XStream is not a Web Service binding layer.
    - XStream does not cover 100% of XML schema concepts.
    - XStream cannot preserve the XML infoset.

    Section 8.5.4 of the JAXB spec clearly states that java.util.Map (and its subtypes) must be supported. This is probably a bug in the reference implementation, you can report this here:
    - https://jaxb.dev.java.net/issues/

    Don't forgot that JAXB implementations are free to go beyond the specification. Below are some of the EclipseLink MOXy extensions:
    - XPath base mapping
    - XML metadata file
    - JPA entity mapping support

    -Blaise

    ReplyDelete
  7. It looks like XStream can map inheritance better than JAXB.

    http://www.natpryce.com/articles/000766.html

    Can JAXB do the same?

    ReplyDelete
  8. Andrew,

    I read the article "Mapping Inheritance Cleanly with XStream", and it demonstrates how to write a converter to represent multiple classes as the same XML element. The JAXB equivalent would be to write an XmlAdapter.

    - XmlAdapter - JAXB's Secret Weapon

    The following posts demonstrate how to easily represent object inheritance in JAXB by leveraging existing XML schema concepts:

    - JAXB and Inheritance - Using the xsi:type Attribute
    - JAXB and Inheritance - Using Substitution Groups

    -Blaise

    ReplyDelete
  9. Nice post. I was really happy with XStream, but JAXB looks cool for those cases also.
    By the way, int the XML output, in XStram you can "map" the qualified name to an alias: xstream.alias("customer", Customer.class);

    ReplyDelete
  10. Nice post. I too was under the impression that to use JAXB, you needed to start out with a schema, generate the java classes, etc. Was this ever the case? Either way, the tutorial you just went through needs to be front and center on Oracle's JAXB main page. It's great to know that JAXB can handle the hard stuff, but it's more important to get the word out how easy it is to use JAXB for the easy stuff. I mean, come on, one of the alternate libraries was probably named "Simple" for a reason. :)

    ReplyDelete
  11. Thanks Ken,

    JAXB 1 required that you start with an XML schema and generate standard interfaces backed by vendor specific implementation classes.

    JAXB 2 moved to POJOs with standard annotations, making the classes portable between JAXB implementations. But somehow the stigma still persisted. It could be because JAXB still offers a schema to Java compiler to generate classes from an XML schema as a convenience mechanism.

    I have also writted a post comparing Simple and JAXB. For that example they are both easy to use. The difference is in all the extra feaures that JAXB implementations (Metro, MOXy, JaxMe, etc) have:

    - http://bdoughan.blogspot.com/2010/10/how-does-jaxb-compare-to-simple.html

    -Blaise

    ReplyDelete
  12. Blaise,
    This is a very informative blog. I'm trying to decide between XStream and JAXB. It was useful to see that you don't have to use an XML schema with JAXB. I'm not a fan of annotations. I just don't like to pollute my code with it. Personal taste...

    You can configure XStream to do your second example by registering aliases. Can this be done in JAXB without annotations? Also, can the examples in JAXB be done without using annotations? Are they required?

    ReplyDelete
  13. Hi Manuel,

    JAXB as defined in the specification (JSR-222) requires annotations. However individual implementations may offer extensions to this.

    EclipseLink MOXy (I'm the tech lead)

    We offer an XML representation of the metadata. An example of it can be seen here:

    - Extending JAXB - Representing Metadata as XML

    Metro JAXB (The reference implementation)

    Can leverage Annox and JAXBIntroductions to get an XML representation of the metadata. With a few lines of code MOXy can also be adapted to work with these formats.

    - http://jaxb.java.net/

    Other JAXB implementations such as JaxMe may address the use case in other ways.

    One of the advantages of JAXB is that it is a standard with multiple implementations. This avoids the vendor lockin you get with a library like XStream.

    -Blaise

    ReplyDelete
  14. Interesting post. I am after XML serialization/deserialization of Java object tree. Is there a way to do this using JAXB without tinkering with XmlAdapter or explicit mappings?

    ReplyDelete
  15. Blaise,

    Excellent post!

    I wonder if you can recommend an approach for handling evoloving classes. Class A, version1 is used at first. Then some of the clients update to Class A version2 (which introduces a new field). But other clients do not upgrade yet. They have the Class A version1 on their classpath. They should be able to read the xml representation of Class A version2 (by just ignoring the new field).

    What's the best way to accomplish that? Can JAXB 'ignore' fields if the class does not have them? Can XStream? I saw that XMT can be used to read version1 with version2 code. But I'm talking about reading version2 with version1 code.

    Any help would be great.

    ReplyDelete
  16. Hi Alex,

    JAXB can be used to marshal an object to XML without the use of any metadata. JAXB metadata only needs to be supplied to override the default behavior. For an example see:

    - http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics

    -Blaise

    ReplyDelete
  17. Hi Anonymous,

    Regarding evolving classes, JAXB handles this case easily. When JAXB finds an element/attribute it does not recognize it is simply ignored.

    From the XStream FAQ if XStream finds an element/attribute it does not recognize an exception is thrown:

    "If a field is removed from the class, deserializing an old version that contains that field will cause an exception."

    -Blaise

    ReplyDelete
  18. Hmm, I looked at it some time ago, but at the time Java 6 bundled jaxb could not do the following:
    - If an object tree I serialize/deserialize has fields of interface types JAXB would not do it OOB
    - If a field is declared as base class, but is assigned a subclass jaxb marshall/unmarshall looses this
    - If I have multiple fields in the object tree that point to the same object instance, after jaxb unmarshalling they will become two independent instances.
    - Java proxy serialization another issue

    Is there an easy way to address all this without creating adapters?

    ReplyDelete
  19. Hi Alex,

    The JAXB specification does not define behavior for interfaces, but this is handled in EclipseLink JAXB (MOXy):

    - MOXy JAXB - Map Interfaces to XML

    JAXB does support inheritance. You need to ensure that the JAXBContext is aware of the subclasses:

    - JAXB and Inheritance - Using the xsi:type Attribute
    - JAXB and Inheritance - Using Substitution Groups

    To handle shared references you do need to supply JAXB metadata to handle this:

    - JAXB and Shared References: @XmlID and @XmlIDREF

    For proxy serialization, refer to the post about mapping to interfaces.

    -Blaise

    ReplyDelete
  20. Hi, what about performance comparison?

    ReplyDelete
  21. Hi byF,

    I do not have a performance comparison for JAXB and XStream. JAXB should be faster since if offers and initialization stage where the metadata can be optimized before unmarshalling/marshalling is done.

    -Blaise

    ReplyDelete
  22. Hi, Blaise,

    Have you used Jaxb in a OSGI/bundle environment? Do you know if it is supported on Felix?

    I am facing a weird problem where the same code executes fine in a standalone java project, but complains that it does not see @XmlRootElement when this code runs in a bundle (in Felix) when it really is there.

    Thanks in advance!

    ReplyDelete
  23. Hi Xianguan,

    Most of the work I have done with JAXB and OSGi has been with Equinox.

    In your manifest you will need to ensure that you are importing all the JAXB packages. You will also need to ensure that JAXB is available as a bundle. GlassFish provides one, and one is available in EclipseLink.

    EclipseLink JAXB (MOXy) is also available as an OSGi bundle and can be obtained from the download site:

    - http://www.eclipse.org/eclipselink/downloads/

    -Blaise

    ReplyDelete
  24. thanks for the answer, Blaise. Really appreciate it.

    ReplyDelete
  25. Does Xstream support multiple namespaces...??
    We can always set QnameMap.setDefaultNamespace() to set a default namesapce for the entire xml..but vat if I have to use more than one namespace in the same xml?

    ReplyDelete
  26. For specifics on how/if XStream handles multiple namespaces you will need to contact someone on that project.

    JAXB implementations (Metro, EclipseLink MOXy, Apache JaxMe) have an elegant solution for this:
    - JAXB & Namespaces

    -Blaise

    ReplyDelete
  27. Hi there - Great information. WIth respect to speed, in my own testing I've seen JAXB outperform XStream on the order of 5 to 1. I'd be interested how it shook out with other peoples' use cases.

    ReplyDelete
  28. BlaZe, you are the man. This page helped me tremendously decide between JAXB and XStream. It has so much useful information (annotations esp.). I could totally build my marshalling strategy without creating any XSD etc...beautiful.

    ReplyDelete
  29. Hi Amit,

    I hope that means you chose JAXB :).

    -Blaise

    ReplyDelete
  30. Hello Blaise
    Please, as I implement the @xmlInverseReference of JAXB in XStream ?

    Thanks

    ReplyDelete
  31. Hi Odete,

    I am not aware if XStream has an equivalent of @XmlInverseReference. I'm the EclipseLink JAXB (MOXy) lead, and am more than happy to help you with MOXy (or any JAXB implementation), but I can't spend any cycles helping with XStream.

    -Blaise

    ReplyDelete
  32. Hello Blaise,

    Is there any possibility in JAXB to marshall all Object of a given ClassZ (e.g. the Date or a CustomClass) depending on some dynamic data (e.g date format, which changes for each object instance)?

    With @XmlAdapter I will have to annotate all properties of type ClassZ with @XmlAdapter and constructing and adapter supposes other 2(or 3) classes.

    ReplyDelete
  33. The following may help:

    1. You can use the @XmlSchemaType at the field/property level to specify the XML representation of data:
    - JAXB and Date/Time Properties

    2. You can register an XmlAdapter for all classes of a particular type at the package level:
    - JAXB and Joda-Time: Dates and Times

    3. You can set initialized instances of XmlAdapter on Marshaller and Unmarshaller. The following answer I gave to a question on Stack Overflow demonstrates this concept in action:
    - http://stackoverflow.com/questions/7278406/serialize-a-jaxb-object-via-its-id/7285517#7285517

    -Blaise

    ReplyDelete