Latest News

Sunday 1 November 2009

ReST Web Services on Google App Engine using NetBeans 6.7

When Google announced early this year the availability of the Java language on their cloud system “App Engine”, this was turning point for Java on the web. The reason I am saying that is due to a simple questions; how many hosting providers support Java? And providing free hosting for that purpose... This was a good move in the direction of the JAVA community and the vast list of all the languages that run on the JVM.  But App Engine does not support the full range of the J2EE API. If you are looking to build any EJB, SOAP services or anything that access the file system, then the App Engine is not for you as it does not support it. To make matter worst, some URL connections are not supported by the Google cloud services. I am looking forward to the day when JBoss Seam will be supported entirely by their services without having to hack the code. Alright, it is not that bad; Google App engine supports a number of Java EE frameworks such as Spring.

Alright people, this was a long introduction but I believe it is worth it. You cannot create web services such as SOAP in the Google App Engine therefore, in this short article, I will show you how to develop a ReST based web services that works with the App Engine using NetBeans and Jersey API. Actually, NetBeans comes with Jersey support out the box. Now, let’s get started.
In order to follow the instructions, you will need the following:

NetBeans 6.7+

Google App Engine SDK

Google App Engine Plugin for NetBeans

I would expect you to know to be familiar with JAVA EE development and Google App Engine development. Once you have all the software and components installed, now we can start.

1.    Create a database structure to store your data. I used MySQL Workbench to design my DB structure (Google App Engine does not used MySQL and does not have plan to support it in the future). This schema is to help you understand the relationship between your entities. You can use any UML tools to design your objects’ relationship. There is a reason I chose to design DB in MySQL, the application generates SQL script which I will upload to MySQL DB. I will show you in the next step the main benefits.
 

2.    Based on your DB schema, create a database. You can use any database you want. I used MySQL to initially store my entities.


3.    Launch your NetBeans application and create new Web Application.
 

3.1    Choose Google App Engine as deployment server, click here to see how to register the App Engine in NetBeans.



4.    Now click on: File -> New File. In the popup window, choose Web Services in the Categories panel and RESTFul Web Services from Database and click next.
 

5.    Choose your the database that you want to generate your Entity classes from and click next. ( in the screenshot I am using the sample DB which came with the NetBeans and JAVA DB server. This is just for illustration purposes only as I have previously generated my Entity Classes from the DB schema I generated in step 1).


6.    Check your Class Names and how they relate to the database. Make any changes that you require in this screen, and then click next.
 

7.    In the next screen, just accept the default values and click finish.
 


Well we have done the hard parts. There is another step that missed out due to the fact that I already written the application. When generating Entities from Database, if you do not have a persistence unit available, it will ask to generate one. Here is more information on how to create a persistence unit with NetBeans. Make sure to make sure to choose “Create” as the table generation strategy.
 


By Now, you should be aware that we have create a back-end application store which we can call using normal http post, get, delete and create. NetBeans RestFull methods allows to use XML or JSON to send data to the services. The responses MIME can be anything you like as long as the application server supports it.
WARNING: JERSEY XML processing is not supported by Google App Engine as it uses JAXB. JAXB accesses API which is forbidden by the App Engine stack. If testing the application on the App engine, use the JSON MIME for your data.
Ok so we have generate the classes and methods require to expose our back-end to other application. As it is, this will not work on Google App Engine so we need to make a final change, this time we need to change the persistence.xml file manually. In the project window under the name of your project, click on Configuration files -> persistence.xml and open the file in the editor. Once the file is open in the editor, click on the XML tab and make the necessary changes to make it look like the screenshot.
 

Here is the content of persistence.xml; modify to reflect your entities and make sure the name of the provider is the same as mine and the properties are exactly the same.

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
        <persistence-unit name="ReSTWebApplicationPU" transaction-type="RESOURCE_LOCAL">
            <provider>org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider</provider>
            <class>com.test.api.Userlogs</class>
            <class>com.test.api.Customer</class>
            <class>com.test.api.User</class>
            <class>com.test.api.Business</class>
            <class>com.test.api.Reviews</class>
            <exclude-unlisted-classes>false</exclude-unlisted-classes>
            <properties>
                <property name="datanucleus.NontransactionalRead" value="true"/>
                <property name="datanucleus.NontransactionalWrite" value="true"/>
                <property name="datanucleus.ConnectionURL" value="appengine"/>
            </properties>
        </persistence-unit>
    </persistence>


Now we are ready to run the application and test it in our local environment. Right click your project name in the projects window and click Test RestFul web services, your favourite web browser with page that shows your resources. You can test your services by clicking on the nodes and or drilling through the nodes.
 

You can also use the Firefox RESTClient Plugin to test your app. Also, Google App Engine does not fully support JPA and might throw some exception about not supporting “integer type object for primary key”. If you do experience this issue, change the type of your key.
This is it for now, looking forward to your feedback, good or bad, they are all welcome. Also, if you need JAVA EE help, contact me directly. Also join me on facebook. Hope the guide or tutorial or whatever you call it, was good enough to help you with something.

Please support my blog and its advertisers by clicking on the interesting products/ services on the right (Google ads).  Cheers.





  • Blogger Comments
  • Facebook Comments

20 comments :

  1. Very, very interesting...thanks much for laying this out.

    ReplyDelete
  2. thnax for the comments guys.

    ReplyDelete
  3. nice blog.

    But in google apps engine , we can go for many-many relations generated from the netbeans from tables

    ReplyDelete
  4. it's a valid try , but im getting follwoing exception:

    [java] java.lang.NoClassDefFoundError: javax.naming.InitialContext is a restricted class. Please see the Google App Engine developer's guide for more details.
    [java] at com.google.appengine.tools.development.agent.runtime.Runtime.reject(Runtime.java:51)
    [java] at com.sun.jersey.spi.container.servlet.ServletContainer.getContext(ServletContainer.java:654)
    [java] at com.sun.jersey.spi.container.servlet.ServletContainer.validate(ServletContainer.java:629)
    [java] at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:621)
    [java] at com.sun.jersey.spi.container.servlet.ServletContainer.load(ServletContainer.java:538)
    [java] at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:197)
    [java] at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:433)
    [java] at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:256)
    [java] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
    [java] at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:612)
    [java] at org.mortbay.jetty.servlet.Context.startContext(Context.java:139)
    [java] at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1218)
    [java] at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:500)
    [java] at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
    [java] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
    [java] at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)
    [java] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
    [java] at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)
    [java] at org.mortbay.jetty.Server.doStart(Server.java:217)
    [java] at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
    [java] at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:188)
    [java] at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:120)
    [java] at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:217)
    [java] at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:162)
    [java] at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
    [java] at com.google.appengine.tools.development.DevAppServerMain.(DevAppServerMain.java:113)
    [java] at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:89)
    [java] Feb 13, 2010 8:21:03 PM com.google.apphosting.utils.jetty.JettyLogger warn
    [java] WARNING: failed com.google.apphosting.utils.jetty.DevAppEngineWebAppContext@1bc82e7{/,C:\Users\raghu\Documents\NetBeansProjects\WebApplication1\build\web}
    [java] java.lang.NoClassDefFoundError: javax.naming.InitialContext is a restricted class. Please see the Google App Engine developer's guide for more details.
    [java] at com.google.appengine.tools.development.agent.runtime.Runtime.reject(Runtime.java:51)
    [java] at com.sun.jersey.spi.container.servlet.ServletContainer.getContext(ServletContainer.java:654)
    [java] at com.sun.jersey.spi.container.servlet.ServletContainer.validate(ServletContainer.java:629)
    [java] at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:621)

    ReplyDelete
  5. please give some sample project with lib list. it would help ..

    tx

    ReplyDelete
  6. @Raghunath

    I did not get that error and Jersey is compatible with Google App Engine. Can you describe your problem in more details.

    ReplyDelete
  7. @Raghunath

    Have you tried the samples with App Engine SDK 1.2.5 as it has been reported that App Engine SDK 1.3.0 seems to report some errors.

    ReplyDelete
  8. @Raghunath

    The problem is that GAE doesn't support EJB and Jersey gets barred while trying to look up JNDI via javax.naming.InitialContext..

    A solution for this is found here:
    http://lqd.hybird.org/journal/?p=123

    The above works on Jersey 1.0, for some reason fails on 1.1..

    ReplyDelete

  9. I feel satisfied to read your blog, you have been delivering a useful & unique information to our vision even you have explained the concept as deep clean without having any uncertainty, keep blogging. Google cloud Online course

    ReplyDelete
  10. Excellent Blog! I would like to thank for the efforts you have made in writing this post. I am hoping the same best work from you in the future as well. I wanted to thank you for this website! Thanks for sharing. Web Services!

    ReplyDelete

Item Reviewed: ReST Web Services on Google App Engine using NetBeans 6.7 Description: Rating: 5 Reviewed By: Unknown
Scroll to Top