Lqd's Journal

Icon

It's actually pronounced liquid!

Hacking Jersey/JAX-RS to run RESTful web services on Google AppEngine/Java

Update: this article is about Jersey 1.0.2, i’ll update the modifications i made for the 1.1.0-ea version soon.

Jersey doesn’t run out of the box on GAE, and since i can’t wait for a new release to try RESTful services on AppEngine/Java, let’s modify its servlet container so it will at least run basic samples.

I really find Jersey/JAX-RS compelling, while others think it could be the ultimate framework, and with all the recent buzz about the AppEngine platform, i wanted to try and make the two meet, grab a little dinner, a glass of wine or two, and make sweet web service babies. That didn’t go as easily as I planned, but after a little hacking i was able to run basic examples, which is probably enough for now, until a later release fixes the issues.

In this post i’ll describe what i did to make Jersey’s basic servlet example work (ie. what i broke) and provide you with the code (code + binary here) so you can try it on your own.

AppEngine runs a tight ship with strict security policies, which caused most of the errors you get using Jersey: classes you can’t access inside their sandbox. I’ve done my best bypassing those errors, and in doing so i actually removed and broke features, some of which i know about, the others, well, i don’t (:

The people following my twitter stream know i learned the hard way that the dev server google provides with its eclipse plugin doesn’t enforce the same security policies as their appspot servers (why is that is a question to which i don’t have the answer), and the kicker is that Jersey runs fine in their dev server….

The first major error you encounter is related to javax.naming.InitialContext, the second one to JAXB binding for WADL generation. I removed both the WADL pregeneration and root resources registration in the JNDI context. I don’t care much for WADL so it’s not a big loss anyway, however i’m not totally sure how the JNDI context is used inside Jersey. This might break something more useful.

A couple more classloader errors, and other tiny issues, and we’re good to go.

Here’s how to make the Jersey basic servlet sample (simple-servlet) run on AppEngine (which you’ll be able to see here for a little while, if you want to test it. It comes with a little ajax ui changing Accept headers, choosing resources to test, etc)

Create a GAE using the Google plugin for Eclipse, add the jersey jars into the war/WEB-INF/lib directory (i used the jersey archive found here to get Jersey, its dependencies and the samples), while you’re at it also add the modified jersey servlet container there, jersey-appengine-container_0.1.jar found in the linked zip file.

Add the modified servlet (org.hybird.appengine.jersey.container.ServletContainer) to web.xml:

<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.hybird.appengine.jersey.container.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.sun.jersey.samples.servlet.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>

Now you can take the simple-servlet sample, copy its index.html in the war folder, and java source files inside your src. And if i remember correctly, that should be it ^^ and you’ll get the same app as i have.

Since Jersey has so many features (a lot more than the JAX-RS spec would let you believe), i haven’t had the time to test a lot of them yet, and i think other security exceptions are probably waiting for us.