Last week I’ve been playing around with Google App Engine (GAE). Setting up the SDK with Eclipse and the Google Plugin for Eclipse was a breeze. Creating a simple webapp, testing it locally, and deploying it to appspot was a piece of cake. But then I figured I wanted to add a REST interface to my application…
I did not want to use GAE’s Google Cloud Endpoints – using the @Api
annotation – because I didn’t want to tie myself to GAE. I wanted to use the JAX-RS standard so my application is portable across different Java application servers.
So the first option I looked at was Jersey, because I’ve use it before. But because of a incompatibility between asm
versions (see stackoverflow for more details) I quickly decided to look for alternative JAX-RS implementations.
Next, I figured I’d give JBoss’ RESTEasy a try. But for some reason I just couldn’t get it to run on GAE. So after 10 minutes or so, I gave up.
So finally I decided to give Restlet a go, mainly because they offer a GAE edition. And within a couple of minutes I had a very basic REST service up and running. Here’s what I did:
- Fire up Eclipse and create a new Google Web Application project.
- Go to Restlet and download and unzip the GAE Edition of Restlet.
- Add the following jar files from the Restlet distribution to the
war/WEB-INF/lib
folder of the project and to its build path:javax.ws.rs.jar
,org.restlet.jar
,org.restlet.ext.servlet.jar
,org.restlet.ext.jaxrs.jar
, andorg.json.jar
. - Add a very basic POJO:
123456789101112131415161718192021222324package it.jdev.appengine;public class Product {String name;int quantity;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getQuantity() {return quantity;}public void setQuantity(int q) {this.quantity = q;}} - Add a simple REST service:
1234567891011121314151617181920212223242526272829package it.jdev.appengine;import javax.ws.rs.Consumes;import javax.ws.rs.GET;import javax.ws.rs.POST;import javax.ws.rs.Path;import javax.ws.rs.Produces;import javax.ws.rs.core.Response;@Path("products")public class ProductResource {@GET@Produces("application/json")public Product getProduct() {Product product = new Product();product.setName("Nexus 7");product.setQuantity(999);return product;}@POST@Consumes("application/json")public Response createProduct(Product product) {String result = "Product created : " + product;return Response.status(201).entity(result).build();}} - Create the JAX-RS Application:
1234567891011121314151617package it.jdev.appengine;import java.util.HashSet;import java.util.Set;import javax.ws.rs.core.Application;public class ExampleApplication extends Application {@Overridepublic Set<class<?>> getClasses() {Set<class<?>> classes = new HashSet<class<?>>();classes.add(ProductResource.class);return classes;}}</class<?></class<?></class<?> - Next, it is necessary to make the JAX-RS application known to Restlet by extending
org.restlet.ext.jaxrs.JaxRsApplication
12345678910111213package it.jdev.appengine;import org.restlet.Context;import org.restlet.ext.jaxrs.JaxRsApplication;public class MyJaxRsApplication extends JaxRsApplication {public MyJaxRsApplication(Context context) {super(context);this.add(new ExampleApplication());}} - Finally, configure your application to use Restlet in your
web.xml
deployment descriptor:
1234567891011121314151617...<servlet><servlet-name>RestletServlet</servlet-name><servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class><init-param><param-name>org.restlet.application</param-name><param-value>it.jdev.appengine.MyJaxRsApplication</param-value></init-param></servlet><servlet-mapping><servlet-name>RestletServlet</servlet-name><url-pattern>/*</url-pattern></servlet-mapping>...
If you now start your application locally by selecting Run As > (Google) Web Application
and point your web browser to http://localhost:8888/products you should see the following response:
{“name”:”Nexus 7″,”quantity”:999}
Thank you Wim, I resolve adding these libraries in war/WEB-INF/lib directory:
– org.codehaus.jackson.core.jar
– org.codehaus.jackson.mapper.jar
– org.restlet.ext.jackson.jar
For testing it I use this curl command:
curl -v -H “Accept: application/json” -H “Content-type: application/json” -X POST -d ‘{“name”:”xyz”, “quantity”:12}’ http://localhost:8888/products
Thanks for the feedback. Guess I forgot to include the jar files you mention in the example >_o
Hi Wim! Thanks for your article!
I have the same issue of Brian, I don’t understand how to send a json post request.
Could you give me the command of curl for testing the POST function?
Regards,
Federico
Hi Frederico,
Take a look at the answers at http://stackoverflow.com/questions/5658510/curl-json-post-request-via-terminal-to-a-rails-app or http://stackoverflow.com/questions/7172784/how-to-post-json-data-with-curl-from-terminal-commandline-to-test-spring-rest
I hope that these links are helpul.
Regards,
Wim
Hi Brian,
Did you specify the correct Content-Type in the Headers section of the Advanced Rest Client Application? There should be an HTTP header field named Content-Entry with the value application/json (Content-Type: application/json).
Regards,
Wim
Great article.
I can’t get the POST to work though, I keep getting an error: “The given resource variant is not supported.”.
I use restlet 2.1.4 and GAE 1.8.5. I’m using REST Console and Advanced REST client for Google Chrome as test client.
Regards
Brian