In this post I will explain the changes you have to do to get JAXB running on GAE.
This has been discussed in one of the Google appengine developer forums and I think now GAE developers have included JAXB in JRE whitelist too. But below I am going to tell the changes I have done to get my JAXB running on GAE (though it is not required for most of you as now there’s is a support already but for the interested ones below are the changes I had done)
Issues :
- FileOutputStream in com.sun.xml.bind.v2.runtime.MarshallerImpl and javax.xml.bind.helpers.AbstractMarshallerImpl
- use of AWT in com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl
- java.util.logging.ConsoleHandler, which is also not supported by Google App
Engine’s Java runtime environment, but used in javax.xml.bind.ContextFinder
Steps :
- Download JAXB source code from
https://jaxb.dev.java.net/2.1.11/jaxb-ri-2_1_11.src.zip
Put it in an Eclipse project at ~/workspace/jaxb-ri-2_1_11
2. Build the runtime as we need to do this so that generated source gets generated.
3. In com.sun.xml.bind.v2.model.impl.ReferencePropertyInfoImpl.java
Change
boolean isRequired(XmlElementRef ref)
to always return true.
As it deals with something related to compatibility issues in 2.2 API.
The same issue stops xjc subproject from building, but we don’t care about that.
To avoid that I changed the compile task in build.xml to read:
<target
depends=”init-standalone”
description=”compile runtime, and xjc sub-projects”>
<ant dir=”apgen” target=”compile” />
<ant dir=”runtime” target=”compile” />
<ant dir=”runtime-fi” target=”compile” />
<ant dir=”runtime-staxex” target=”compile” />
<ant dir=”runtime-deprecated” target=”compile” />
<!– <ant dir=”xjc” target=”compile” />
<ant dir=”tools” target=”compile” /> –>
</target>
4. Copy runtime/src and runtime/build/src to your GAE project [here called myproj] src dir
runtime/src$ cp com /home/dev/workspace/myproj/src/ -rR
runtime/build/src$ cp * /home/dev/workspace/myproj/src/ -rR
5. Find jaxb-api-src.zip in tools/lib/redist. It contains javax.xml.bind
Unzip that, and put it your myproject src dir
6. Find jsr173_1.0_src.jar; it is in tools/lib/src. This contains javax.xml.stream.XMLStreamWriter and XMLStreamException which we need but aren’t whitelisted.
Extract them and copy to myproject.
src tree should now include
/com/sun/xml/bind
/javax/xml/bind
/javax/xml/stream
7. Add the missing jars
cp tools/lib/redist/jsr173_1.0_api.jar
/home/dev/workspace/myproj/war/WEB-INF/lib/
cp tools/lib/redist/activation.jar /home/dev/workspace/myproj/war/WEB-INF/lib/
cp tools/lib/rebundle/runtime2/*.jar /home/dev/workspace/myproj/war/WEB-INF/lib/
8. Now fix the major issues :-
- com.sun.xml.bind.v2.runtime.MarshallerImpl
Comment out the FileOutputStream part as we won’t have file for marshalling in our case
- javax.xml.bind.helpers.AbstractMarshallerImpl
Comment out
void marshal(Object jaxbElement, File output)
as we won’t be dealing with marshalling of files and also its not supported J
- com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl.java
As AWT is not supported so we have to comment out
PcdataImpl<Image>(Image.class, createXS(“base64Binary”))
convertToBufferedImage(Image image)
Base64Data print(Image v)
- ae.javax.xml.bind.ContextFinder.java
As java.util.logging.ConsoleHandler is not supported comment out the logger part
9. Exclude the classes from validation (right click > Google > App Engine Settings >App Engine > Validation). These are
- com.sun.xml.bind.v2.runtime.property.SingleMapNodeProperty
- com.sun.xml.bind.v2.util.TypeCast
Interestingly, the validator wonn’t complain about javax.xml.bind, now that it is in our source tree. And it’s enough for the app to start in the Jetty simulation environment.
But it will try to use the JAXB in Java 6, not the ones in my source tree. So ename:
- com.sun.xml.bind –> ae.com.sun.xml.bind
- javax.xml.bind –> ae.javax.xml.bind
- javax.xml.stream –> ae.javax.xml.stream
For JAXBContext: ae.com.sun.xml.bind.v2.runtime.JAXBContextImpl
For marshaller: ae.com.sun.xml.bind.v2.runtime.MarshallerImpl
10. Finally in ae.com.sun.xml.bind.v2.runtime.reflect.opt.Injector.java
Comment out
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
defineClass.setAccessible(true);
resolveClass.setAccessible(true);
return null;
}
});
As it will cause create some security related issues.
This will make JAXB running on GAE.
Reference:
http://code.google.com/p/googleappengine/issues/detail?id=1267