Shekhar Gulati is a Java Consultant with over 5 years experience.He is currently working with Xebia India an Agile Software Development company.The postings on this site and on his blog are his own and do not necessarily represent opinion of his employer. His own blog is at http://whyjava.wordpress.com/ and you can follow him on twitter here. Shekhar has posted 25 posts at DZone. View Full User Profile

Creating Application using Spring Roo and Deploying on Google App Engine

07.23.2010
| 41336 views |
  • submit to reddit
Spring Roo is an Rapid Application Development tool which helps you in rapidly building spring based enterprise applications in the Java programming language.  Google App Engine is a Cloud Computing Technology which lets you run your application on Google's infrastructure. Using Spring Roo, you can develop applications which can be deployed on Google App Engine. In this tutorial, we will develop a simple application which can run on Google App Engine.

Roo configures and manages your application using the Roo Shell. Roo Shell can be launched as a stand-alone, command-line tool, or as a view pane in the SpringSource Tool Suite IDE.

Prerequisite
Before we can start using Roo shell, we need to download and install all pre-requites.

  1. Download and install SpringSource Tool Suite 2.3.3. M2. Spring Roo 1.1.0.M2 comes bundled with STS. While installing STS, installer asks for the location where STS should be installed. In that directory, it will created a folder with name "roo-%release_number%" which will contain roo stuff. Add %spring_roo%/roo-1.1.0.M2/bin in your path so that when you can fire roo commands from command line.
  2. Start STS and go to the Dashboard (Help->Dashboard)
  3. Click on the Extensions tab
  4. Install the "Google Plugin for Eclipse" and the "DataNucleus Plugin".
  5. Restart STS when prompted.

After installing all the above we can start building application.

ConferenceRegistration.Roo Application
Conference Registration is a simple application where speaker can register themselves and create a session they want to talk about. So, we will be having two entities Speaker and Presentation. Follow the instructions to create the application:
  1. Open your operating system command-line shell
  2. Create a directory named conference-registration
  3. Go to the conference-registration directory in your command-line shell
  4. Fire roo command. You will see a roo shell as shown below. Hint command gives you the next actions you can take to manage your application.



  5. Type the hint command and press enter.  Roo will tell you that first you need to create a project and for creating a project you should type 'project' and then hit TAB. hint command is very useful as you don't have to cram all the commands it will always give you the next logical steps that you can take at that point.



  6. Roo hint command told us that we have to create the project so type the project command as shown below
    project --topLevelPackage com.shekhar.conference.registration --java 6
    This command created a new maven project with top-level package name as com.shekhar.conference.registration and created directories for storing source code and other resource files. In this command, we also specified that we are using Java  version 6.
  7. Once you have created the project, type in the hint command again, roo will tell you that now you have to set up the persistence. Type the following command
    persistence setup --provider DATANUCLEUS --database GOOGLE_APP_ENGINE --applicationId roo-gae
    This command set up all the things required for the persistence. It creates persistence.xml, adds all the dependencies required for persistence in pom.xml. We have chosen provider as DATANUCLEUS and database as GOOGLE_APP_ENGINE because we are developing our application for Google App Engine and it uses its own datastore.  applicationId is also required when we deploy our application to Google App Engine. Now our persistence set up is completed.
  8. Type the hint command again, roo will tell you that you have to create entities now. So, we need to create our entities Speaker and Presentation. To create Speaker entity, we will type the following commands
    entity --class ~.domain.Speaker --testAutomatically
    field string --fieldName fullName --notNull
    field string --fieldName email --notNull --regexp ^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$
    field string --fieldName city
    field date --fieldName birthDate --type java.util.Date --notNull
    field string --fieldName bio
    The above six lines created an entity named Session with different fields. In this we have used notNull constraint, email regex validation, date field. Spring Roo on app engine does not support enum and references yet which means that you can't define one-one or one-to-many relationships between entities yet. These capabilities are supported on Spring MVC applications but Spring MVC applications can't be deployed on app engine as if now. Spring Roo jira has these issues. They will be fixed in future releases(Hope So :) ).
  9. Next create the second entity of our application Presentation. To create Presentation entity type the following commands on roo shell
    entity --class ~.domain.Presentation --testAutomatically
    field string --fieldName title --notNull
    field string --fieldName description --notNull
    field string --fieldName speaker --notNull
    The above four lines created a JPA entity called Presentation, located in the domain sub-package, and added three fields -- title,description and speaker. As you can see, speaker is added as a String (just enter the full name). Spring Roo on Google App Engine still does not support references.
  10. Now that we have created our entities, we have to create the face of our application i.e. User Interface. Currently, only GWT created UI runs on app engine. So, we will create GWT user interface. To do that type
    gwt setup
    This command will add the GWT controller as well as all the UI required stuff. This command may take couple of minutes if you don't if you don't have those dependencies in your maven repository.
  11. Next you can configure the log4j to Debug level using the following command
    logging setup --level DEBUG
  12. Quit the roo shell
  13. You can easily run your application locally if you have maven installed on your system, simply type "mvn gwt:run" at your command line shell while you are in the same directory in which you created the project. This will launch the GWT development mode and you can test your application. Please note that applications does not run in Google Chrome browser when you run from your development environment. So, better run it in firefox.
  14. To deploy your application to Google App Engine just type
    mvn gwt:compile gae:deploy
    It will ask you app engine credentials(emailid and password).


I hope this tutorial will help you in building applications which can be deployed on Google App Engine using Spring Roo. You can test the application @ http://roo-gae.appspot.com/
Published at DZone with permission of its author, Shekhar Gulati.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Anders Breivik replied on Fri, 2010/08/06 - 7:50am

"Currently, only GWT created UI runs on app engine"

 Is this really correct?

Shekhar Gulati replied on Fri, 2010/08/06 - 1:12pm in response to: Anders Breivik

What I mean with "Currently, only GWT created UI runs on app engine" is that using spring roo you can only only deploy GWT based applications on app engine. Spring Roo also creates application using Spring MVC(with tiles) but those applications does not run on Google App Engine. The reason is that they use one of the libraries which internally use a class blacklisted in app engine. Hope this make it clear !

Ron Sutaria replied on Mon, 2010/10/04 - 1:56am

I am trying out the code that is given here and I'm facing a couple of problems.

When I am trying to run the last step mvn gwt:compile gae:deploy, following is the error I get:

 

-------------------------------------------------------------------------------
Test set: com.shekhar.conference.registration.domain.SpeakerIntegrationTest
-------------------------------------------------------------------------------
Tests run: 9, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.799 sec <<< FAILURE!
testFindSpeaker(com.shekhar.conference.registration.domain.SpeakerIntegrationTest)  Time elapsed: 0.013 sec  <<< FAILURE!
java.lang.AssertionError: Data on demand for 'Speaker' failed to initialize correctly
    at org.junit.Assert.fail(Assert.java:91)
    at org.junit.Assert.assertTrue(Assert.java:43)
    at org.junit.Assert.assertNotNull(Assert.java:524)

 

 

Could you please suggest what could be the possible cause for this error?

 

There is also another question I had. Prior to running mvn gae:deploy, if I try to run the previous command mvn gwt:run - I get the following error in the GWT console:

00:00:01.336  [ERROR] Unable to start AppEngine server
<pre>com.google.apphosting.utils.config.AppEngineConfigException: Welcome files must be relative paths: /
    at com.google.apphosting.utils.config.WebXml.validate(WebXml.java:115)
    at com.google.appengine.tools.development.AbstractContainerService.loadAppEngineWebXml(AbstractContainerService.java:241)
    at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:144)
    at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:222)
    at com.google.appengine.tools.development.gwt.AppEngineLauncher.start(AppEngineLauncher.java:86)
    at com.google.gwt.dev.DevMode.doStartUpServer(DevMode.java:431)
    at com.google.gwt.dev.DevModeBase.startUp(DevModeBase.java:1053)
    at com.google.gwt.dev.DevModeBase.run(DevModeBase.java:795)
    at com.google.gwt.dev.DevMode.main(DevMode.java:282)</pre>

 

 There is also a warning:

00:00:00.815  [WARN] ********************************************************
There is a new version of the SDK available.
-----------
Latest SDK:
Release: 1.3.7
Timestamp: Wed Aug 25 22:10:01 IST 2010
API versions: [1.0]

-----------
Your SDK:
Release: 1.3.4
Timestamp: Sat May 15 02:56:11 IST 2010
API versions: [1.0]

-----------
Please visit http://code.google.com/appengine for the latest SDK.
********************************************************

_________________________________________________________________________________

Would you be able to provide some assistance on how can I get the mvn gwt:run and gae:deploy commands to work on my setup?

 

I greatly appreciate your assitance and the article you have written.

 

Thanks,

Ronak

 

Bilal Dar replied on Thu, 2010/10/07 - 11:41pm

Thanks Shekhar for the post .. It was really good. and it worked .. One observation and this might sound strange ...
If we get error with roo first time in a folder. Starting from scratch from in another folder sometimes does help, since i have seen this issue with problem ranging from persistence setup to unable to locate a certain plugin .. I am not sure what the reason might be for this ..

I have taken a bit of different step from your blog instead of using gwt setup . I used
controller all --package ~.web
things didn't go as planned ...
I am not sure if this is supported yet or not ?


The result is there is no page display. Nothing gets loaded.
This is What I did .. i am using Java 6 on Windows 7 with Spring Roo 1.1.0.M2

// Spring Roo 1.1.0.M2 [rev 0b3543e] log opened at 2010-10-08 00:06:22
project --topLevelPackage com.n2odoc.gae.mvc --java 6 --projectName n2odocgaemvc
persistence setup --provider DATANUCLEUS --database GOOGLE_APP_ENGINE --applicationId sucker123zero
entity --class ~.domain.Doctors
field string --fieldName FirstName
field string --fieldName LastName
entity --class ~.domain.EmergencyCase
field string --fieldName CaseId
field string --fieldName ExpertId
field string --fieldName RequestId
controller all --package ~.web
logging setup --level DEBUG
exit


This is the Exception from the log ...

10-07 09:22PM 05.946 /$%7Bfavicon%7D 304 31ms 58cpu_ms 0kb Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10,gzip(gfe) See details 70.26.52.182 - - [07/Oct/2010:21:22:05 -0700] "GET /$%7Bfavicon%7D HTTP/1.1" 304 0 - "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10,gzip(gfe)" "5.latest.sucker123zero.appspot.com" ms=31 cpu_ms=58 api_cpu_ms=0 cpm_usd=0.001660 2. W 10-07 09:22PM 05.961 /$%7Bfavicon%7D java.lang.IllegalArgumentException: Illegal group reference at java.util.regex.Matcher.appendReplacement(Matcher.java:725) at org.tuckey.web.filters.urlrewrite.utils.WildcardMatcher.replaceAll(WildcardMatcher.java:118) at org.tuckey.web.filters.urlrewrite.RuleBase.matchesBase(RuleBase.java:242) at org.tuckey.web.filters.urlrewrite.NormalRule.matches(NormalRule.java:88) at org.tuckey.web.filters.urlrewrite.RuleChain.doRuleProcessing(RuleChain.java:79) at org.tuckey.web.filters.urlrewrite.RuleChain.process(RuleChain.java:133) at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:140) at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:90) at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:417) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:97) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:238) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923) at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:135) at com.google.apphosting.runtime.JavaRuntime.handleRequest(JavaRuntime.java:251) at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:6784) at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:6782) at com.google.net.rpc.impl.BlockingApplicationHandler.handleRequest(BlockingApplicationHandler.java:24) at com.google.net.rpc.impl.RpcUtil.runRpcInApplication(RpcUtil.java:398) at com.google.net.rpc.impl.Server$2.run(Server.java:852) at com.google.tracing.LocalTraceSpanRunnable.run(LocalTraceSpanRunnable.java:56) at com.google.tracing.LocalTraceSpanBuilder.internalContinueSpan(LocalTraceSpanBuilder.java:576) at com.google.net.rpc.impl.Server.startRpc(Server.java:807) at com.google.net.rpc.impl.Server.processRequest(Server.java:369) at com.google.net.rpc.impl.ServerConnection.messageReceived(ServerConnection.java:442) at com.google.net.rpc.impl.RpcConnection.parseMessages(RpcConnection.java:319) at com.google.net.rpc.impl.RpcConnection.dataReceived(RpcConnection.java:290) at com.google.net.async.Connection.handleReadEvent(Connection.java:474) at com.google.net.async.EventDispatcher.processNetworkEvents(EventDispatcher.java:831) at com.google.net.async.EventDispatcher.internalLoop(EventDispatcher.java:207) at com.google.net.async.EventDispatcher.loop(EventDispatcher.java:103) at com.google.net.rpc.RpcService.runUntilServerShutdown(RpcService.java:251) at com.google.apphosting.runtime.JavaRuntime$RpcRunnable.run(JavaRuntime.java:418) at java.lang.Thread.run(Thread.java:636)

Any help would be much appreciated

Bilal Dar replied on Thu, 2010/10/07 - 11:44pm in response to: Bilal Dar

got the answer it is not supported yettttttttt

Kai Wähner replied on Sun, 2011/04/10 - 6:33am

Hey Shekhar,

good article. But did you also realize some relationships between entities? I think "OneToMany" and so on do not work with GAE?

Best regards,

Kai Wähner (Twitter: @KaiWaehner)

Palak Darji replied on Tue, 2014/01/21 - 3:05am

Where should i type that command: mvn gwt:compile gae:deploy

I have typed it in cmd which locates to my project root folder. but it says: 

" No plugin found for prefix 'gae' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (C:\Users\Palak\.m2\repository), spring-maven-release (http://maven.springframework.org/release), spring-maven-milestone (http://maven.springframework.org/milestone), spring-roo-repository (http://spring-roo-repository.springsource.org/release), DataNucleus_2 (http://www.datanucleus.org/downloads/maven2/), central (http://repo.maven.apache.org/maven2)] -> [Help 1]"


gae is not working in cmd and maven run config of sts.

Please, help me to get rid of this..  thnx

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.