{"id":123,"date":"2009-04-10T23:09:53","date_gmt":"2009-04-10T22:09:53","guid":{"rendered":"http:\/\/lqd.hybird.org\/journal\/?p=123"},"modified":"2013-06-24T18:01:59","modified_gmt":"2013-06-24T17:01:59","slug":"hacking-jerseyjax-rs-to-run-restful-web-services-on-google-appenginejava","status":"publish","type":"post","link":"https:\/\/lqd.hybird.org\/journal\/?p=123","title":{"rendered":"Hacking Jersey\/JAX-RS to run RESTful web services on Google AppEngine\/Java"},"content":{"rendered":"<p>Update: this article is about Jersey 1.0.2, i&#8217;ll update the modifications i made for the 1.1.0-ea version soon.<\/p>\n<p>Jersey doesn&#8217;t run out of the box on GAE, and since i can&#8217;t wait for a new release to try RESTful services on AppEngine\/Java, let&#8217;s modify its servlet container so it will at least run basic samples.<\/p>\n<p>I really find Jersey\/JAX-RS compelling, while <a href=\"http:\/\/macstrac.blogspot.com\/2009\/01\/jax-rs-as-one-web-framework-to-rule.html\">others think it could be the ultimate framework<\/a>, 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&#8217;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.<\/p>\n<p>In this post i&#8217;ll describe what i did to make Jersey&#8217;s basic servlet example work (ie. what i broke) and provide you with the code (code + binary <a href=\"http:\/\/lqd.hybird.org\/files\/appengine\/jersey-appengine-container_0.1.zip\">here<\/a>) so you can try it on your own.<\/p>\n<p>AppEngine runs a tight ship with strict security policies, which caused most of the errors you get using Jersey: classes you can&#8217;t access inside their sandbox. I&#8217;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&#8217;t (:<\/p>\n<p>The people following my <a href=\"http:\/\/www.twitter.com\/lqd\">twitter stream<\/a> know i learned the hard way that the dev server google provides with its eclipse plugin doesn&#8217;t enforce the same security policies as their appspot servers (why is that is a question to which i don&#8217;t have the answer), and the kicker is that Jersey runs fine in their dev server&#8230;.<\/p>\n<p>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&#8217;t care much for WADL so it&#8217;s not a big loss anyway, however i&#8217;m not totally sure how the JNDI context is used inside Jersey. This might break something more useful.<\/p>\n<p>A couple more classloader errors, and other tiny issues, and we&#8217;re good to go.<\/p>\n<p>Here&#8217;s how to make the Jersey basic servlet sample (simple-servlet) run on AppEngine (which you&#8217;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)<\/p>\n<p>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 <a href=\"https:\/\/jersey.dev.java.net\/source\/browse\/*checkout*\/jersey\/tags\/jersey-1.0.2\/jersey\/dependencies.html\">here<\/a> to get Jersey, its dependencies and the samples), while you&#8217;re at it also add the modified jersey servlet container there, jersey-appengine-container_0.1.jar found in the linked zip file.<\/p>\n<p>Add the modified servlet (org.hybird.appengine.jersey.container.ServletContainer) to web.xml:<\/p>\n<p>[sourcecode language=&#8217;xml&#8217;]<br \/>\n<servlet><br \/>\n<servlet-name>Jersey Web Application<\/servlet-name><br \/>\n<servlet-class>org.hybird.appengine.jersey.container.ServletContainer<\/servlet-class><br \/>\n<init-param>\n<param-name>com.sun.jersey.config.property.packages<\/param-name>\n<param-value>com.sun.jersey.samples.servlet.resources<\/param-value>\n<\/init-param><br \/>\n<load-on-startup>1<\/load-on-startup><br \/>\n<\/servlet><br \/>\n<servlet-mapping><br \/>\n<servlet-name>Jersey Web Application<\/servlet-name><br \/>\n<url-pattern>\/resources\/*<\/url-pattern><br \/>\n<\/servlet-mapping><br \/>\n[\/sourcecode]<\/p>\n<p>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&#8217;ll get the same app as i have.<\/p>\n<p>Since Jersey has so many features (a lot more than the JAX-RS spec would let you believe), i haven&#8217;t had the time to test a lot of them yet, and i think other security exceptions are probably waiting for us.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update: this article is about Jersey 1.0.2, i&#8217;ll update the modifications i made for the 1.1.0-ea version soon. Jersey doesn&#8217;t run out of the box on GAE, and since i can&#8217;t wait for a new release to try RESTful services on AppEngine\/Java, let&#8217;s modify its servlet container so it will at least run basic samples. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[10,9,8],"class_list":["post-123","post","type-post","status-publish","format-standard","hentry","category-java","tag-google-appengine","tag-jax-rs","tag-jersey"],"_links":{"self":[{"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=\/wp\/v2\/posts\/123","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=123"}],"version-history":[{"count":8,"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=\/wp\/v2\/posts\/123\/revisions"}],"predecessor-version":[{"id":145,"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=\/wp\/v2\/posts\/123\/revisions\/145"}],"wp:attachment":[{"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=123"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=123"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lqd.hybird.org\/journal\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=123"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}