Description | JAXB | Simple XML |
---|---|---|
The RSS element that is being deserialized has a version attribute on it but I do not wish to model this in the Java class. I only want to deserialize the channel element | @XmlRootElement(name="rss") static class Rss { @XmlElement(name="channel") Channel channel; } | @Root(name="rss", strict=false) static class Rss { @Element(name="channel") Channel channel; } |
The channel element contains a list of item elements without any wrapper element enclosing the whole list. | static class Channel { @XmlElement(name="item") List<Item> items; } | @Root(strict=false) static class Channel { @ElementList(entry="item", inline=true) List<Item> items; } |
A List with a wrapper element. | @XmlElementWrapper(name="customfieldvalues") @XmlElement(name="customfieldvalue") List<String> customfieldvalues; | @ElementList(entry="customfieldvalue", required=false) List<String> customfieldvalues; |
Deserialize | JAXBContext jaxbContext = JAXBContext.newInstance(Rss.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); Rss rss = (Rss) unmarshaller.unmarshal(in); | Serializer serializer = new Persister(); Rss rss = serializer.read(Rss.class, in); |
Head of Development, Software Architect and Developer by day. Data Science and Raspberry Pi dabbler by night.
Showing posts with label simple xml. Show all posts
Showing posts with label simple xml. Show all posts
2009-11-15
Converting from JAXB to Simple XML
Since JAXB doesn't work on Google App Engine but Simple XML does I have been converting my application. I'm using XML in quite a loose way; I have only annotated my classes for the elements and attributes which I want to extract from the larger XML document. JAXB is more forgiving when used in this way, however with a few extra parameters the same can be achieved with Simple XML. Here is a table of a few things I had to convert:
Labels:
google app engine,
jaxb,
simple xml,
xml
2009-11-08
Using Simple XML instead of JAXB on Google App Engine
In my previous post I said that I was going to try using a hack to get around the lack of support for JAXB in Google App Engine. Not only did this feel bad but also it didn't work for me, despite all the changes that had been made to circumvent the non-whitelisted classes. I still got various java.lang.NoClassDefFoundError exceptions.
So I decided to try Simple XML Serialization instead. This worked really well and caused no problems in the Local environment. However, when I deployed this to Google I was hit by the Sandbox limitations for Reflection. When Simple scans your classes to build its "schema" it calls setAccessible(true) on every method and constructor it finds all the way up the hierarchy to Object. This violates the sandbox restriction: "An application cannot reflect against any other classes not belonging to itself, and it can not use the
For my purposes, and probably the majority case, I do not need to serialize or deserialize to any non-public method of any superclasses other than my own. So given this I decided to absorb any SecurityExceptions thrown during the scanning process thus leaving those methods out of the "schema". Two minor changes are required to the source. The scan methods in org.simpleframework.xml.core.ClassScanner and org.simpleframework.xml.core.ConstructrorScanner both need a try..catch block added like so:
UPDATE:
The author of Simple has responded to my post on the mailing list saying that my fix above will be added to the next release.
So I decided to try Simple XML Serialization instead. This worked really well and caused no problems in the Local environment. However, when I deployed this to Google I was hit by the Sandbox limitations for Reflection. When Simple scans your classes to build its "schema" it calls setAccessible(true) on every method and constructor it finds all the way up the hierarchy to Object. This violates the sandbox restriction: "An application cannot reflect against any other classes not belonging to itself, and it can not use the
setAccessible()
method to circumvent these restrictions." App Engine throws a SecurityException when you try to call setAccessible(true) on one of its classes.For my purposes, and probably the majority case, I do not need to serialize or deserialize to any non-public method of any superclasses other than my own. So given this I decided to absorb any SecurityExceptions thrown during the scanning process thus leaving those methods out of the "schema". Two minor changes are required to the source. The scan methods in org.simpleframework.xml.core.ClassScanner and org.simpleframework.xml.core.ConstructrorScanner both need a try..catch block added like so:
//ClassScanner private void scan(Class real, Class type) throws Exception { Method[] method = type.getDeclaredMethods(); for(int i = 0; i < method.length; i++) { Method next = method[i]; try { if(!next.isAccessible()) { next.setAccessible(true); } scan(next); } catch (SecurityException e) { // Absorb this } } } //ConstructorScanner private void scan(Class type) throws Exception { Constructor[] array = type.getDeclaredConstructors(); for(Constructor factory: array){ ClassMap map = new ClassMap(type); try { if(!factory.isAccessible()) { factory.setAccessible(true); } scan(factory, map); } catch (SecurityException e) { // Absorb this } } }This works well now in the Local and Deployed environments. Perhaps Simple would benefit from a mode or an option on the @Root annotation to specify the depth of class scanning as an alternative to this work around. I will post this on the Simple mailing list and report back.
UPDATE:
The author of Simple has responded to my post on the mailing list saying that my fix above will be added to the next release.
Labels:
google app engine,
jaxb,
simple xml,
xml
Subscribe to:
Posts (Atom)