I’ve been pretty frustrated with Sun’s JAXB and JBoss’s JBossXB implementations. Here’s why:
* JAXB is not very extendable. For example, I’d love to be able to define custom annotations that trigger callback APIs so that I can read/write custom properties from an XML document. For example, ever try to do Map support? I’ve also wanted to convert URLs to/from Link objects in resteasy with hooks into RESTEasy runtime for automatic URL writing. I just couldn’t find a way to do it within resteasy.
* JAXB (both Sun’s and JBoss’s) is very slow to initialize. Yeah, they parse very fast, but initialization speed is very slow because it has to do a lot of reflection on the classes that make up the JAXBContext and build a lot of data structures to do quick parsing. You might be saying, “Big Deal!”. But what I’ve found with JAXB and JBoss’s impl is that for the meta-models we’re trying to parse in JBoss AS, it can take as much as 1 second to initialize all the models. That’s 1 second more added to boot time. 1 second to make embedded/unit testing slower.
So, this is why I started the fast-jaxb project under the RESTEasy SVN. The way it works is that you provide it a set of classes and it generates Java code that uses SAX to parse XML. The problem is, I haven’t had the time finish it, which is why I’m blogging to ask if anybody is interested in taking it over (or suggesting a good alternative for solving the goals/problems mentioned above). Fast-JAXB has basically no initialization overhead compared to Sun’s JAXB implimentation. I haven’t worked on the extension points though, nor do I support all the JAXB annotations. I have also only worked on parsing XML, not generating XML. Anybody interested in taking it over and driving it? Give me a ping here on this blog…
Jun 29, 2010 @ 16:20:10
Have you considered using a javax.xml.bind.annotations.adapters.XmlAdapter?:
http://java.sun.com/javase/6/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html
The Javadoc itself demonstrates how to handle Map using an XmlAdapter, you can also use it to convert objects to/from link representations.
Jun 29, 2010 @ 16:28:19
Have you tried to use the XmlAdapter example to implement Map support? I have, and failed. Maybe I’m just stupid. Another example is, I want to get information from a custom annotation to decide how to build the injected object from an XML document (and vice versa). Impossible with JAXB.
Jun 29, 2010 @ 18:56:39
Here is how the example is supposed to work:
In this example java.util.HashMap is the unmappable object, the example below could be modified for any unmappable object.
For all references to the umappable object, you annotate the property with @XmlJavaTypeAdapter. The value of this annotation is the class you are going to use to convert the unmappable object into a mappable one:
import java.util.HashMap;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {
@XmlJavaTypeAdapter(MyHashMapAdapter.class)
HashMap hashmap;
public Foo() {
hashmap = new HashMap();
}
public HashMap getHashmap() {
return hashmap;
}
public void setHashmap(HashMap hashmap) {
this.hashmap = hashmap;
}
}
The following XmlAdapter is used to convert the unmappable java.util.HashMap into a mappable MyHashMapType:
import java.util.HashMap;
import java.util.Map.Entry;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public final class MyHashMapAdapter extends XmlAdapter<MyHashMapType,HashMap> {
@Override
public MyHashMapType marshal(HashMap arg0) throws Exception {
MyHashMapType myHashMapType = new MyHashMapType();
for(Entry entry : arg0.entrySet()) {
MyHashEntryType myHashEntryType = new MyHashEntryType();
myHashEntryType.key = entry.getKey();
myHashEntryType.value = entry.getValue();
myHashMapType.entry.add(myHashEntryType);
}
return myHashMapType;
}
@Override
public HashMap unmarshal(MyHashMapType arg0) throws Exception {
HashMap hashMap = new HashMap();
for(MyHashEntryType myHashEntryType : arg0.entry) {
hashMap.put(myHashEntryType.key, myHashEntryType.value);
}
return hashMap;
}
}
The mappable object MyHashMapType (and MyHashEntryType) look like:
import java.util.ArrayList;
import java.util.List;
public class MyHashMapType {
public List entry = new ArrayList();
}
and
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlValue;
public class MyHashEntryType {
@XmlAttribute
public Integer key;
@XmlValue
public String value;
}
The following code can be used to test the above:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(Foo.class);
Foo foo = new Foo();
foo.getHashmap().put(1, "One");
foo.getHashmap().put(2, "Two");
foo.getHashmap().put(3, "Three");
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(foo, System.out);
}
}
Dec 18, 2010 @ 10:34:19
How to use with jaxb and fastinfoset in resteasy.if possible,post some references or an example for the same.