Ardent Lord

That's me

Blog

Spring 3.0 on Google App Engine

Posted by Idris on April 19, 2009 at 1:27 PM

-- Note: If you just want the nitty gritty without my blabbing, ignore the first paragraph --

So last week I got the inspiration to try out Google App Engine after reading about the new Java support. I searched around to find some resources on getting Spring running on App Engine, but the resources were surprisingly scarce. Google points you to their "autoshoppe" example, which is a little incomplete in terms of setup and what libraries you need. Ironically, Spring Source's post about App Engine was talking about using Groovy, not Spring. Finally I found a blog entry by Sikeh. So I got a nice Hello World up and running on Spring 2, thanks to Sikeh, but I wasn't satisfied yet. I wanted Spring 3. Spring 2 is so... 2008. So I started bringing in some Spring 3 (M2) jars, played around a little more, did some Googling, and finally got Spring 3 up and running.

Here's how you'll need to setup the directory structure:

  1. Setup a Google App Engine project (I used the Eclipse plugin)
  2. Download Spring 3.0.0.M2 (or the latest version)
  3. Copy the following jar files from Spring into the /war/WEB-INF/lib directory:
    org.springframework.beans-3.0.0.M2.jar
    org.springframework.context-3.0.0.M2.jar
    org.springframework.core-3.0.0.M2.jar
    org.springframework.expression-3.0.0.M2.jar
    org.springframework.web-3.0.0.M2.jar
    org.springframework.web.servlet-3.0.0.M2.jar
  4. Spring also depends on the following jars, which you can search for around the internet, or download from my Spring Example git repository:
    antlr-3.0.1.jar
    asm-2.1.jar
    asm-commons-2.1.jar
    commons-logging-1.1.1.jar
  5. Finally, you'll need to rename the commons-logging-1.1.1 jar to something else, like commons-logging.jar (thanks to Martin for this tip!)

Next, you'll need to configure your web.xml for Spring. In web.xml I added a catch-all mapping to my Spring dispatcher:

<servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping>

WARNING: If you use a catch-all (/*) url-pattern, the application will not work in development mode (locally), but will work on the AppEngine server. I believe this is a known bug.

For my dispatcher-servlet.xml: (also in /war/WEB-INF/)

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="example.controllers" /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/views/" p:suffix=".jsp" /> </beans>

You obviously want to change the base-package to whatever package you want. I use the InternalResourceViewResolver, and put all my views in /WEB-INF/views/. Finally, here's my (uninteresting) applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> <beans> </beans>

Now we're all done with setup! Just create a controller and a view. I made a simple hello.jsp view that outputs the request parameter "name". Here's the controller:

package example.controllers.hello; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { @RequestMapping("/hello/{name}") public String hello(@PathVariable String name, Model model) { model.addAttribute("name", name); return "hello/hello"; } }

So there you have it. Spring up and running on Google App Engine. You can see it in action at http://springexample.appspot.com/, or you can get the source at http://github.com/idris/spring-example-gae/. For now, this is all just a Hello Wold. I'll post more functionality later... Feel free to suggest topics in the comments!

Categories: None

Post a Comment

Oops!

Oops, you forgot something.

Oops!

The words you entered did not match the given text. Please try again.

Already a member? Sign In

28 Comments

Reply cheolho
10:09 PM on April 22, 2009 
WARNING: If you use a catch-all (/*) - I got this working in hosted mode but found other issues with Jetty. Can I ask what happens when you try to use this from your demo ? Try enabling logging for spring, and see what dispatcher output is. I will address this in my next blog, and show what i had to do to get it working. But from what you have in your demo .. this should work.
Reply Idris
10:23 PM on April 22, 2009 
cheolho says...
WARNING: If you use a catch-all (/*) - I got this working in hosted mode but found other issues with Jetty. Can I ask what happens when you try to use this from your demo ? Try enabling logging for spring, and see what dispatcher output is. I will address this in my next blog, and show what i had to do to get it working. But from what you have in your demo .. this should work.


Sure, it works fine on the appserver ( http://springexample.appspot.com ), but when I run it locally, everything is a 404. The static files give a 404, and my controller yields a strange 404 for RequestURI=/WEB-INF/views/hello/hello.jsp
Reply Idris
10:25 PM on April 22, 2009 
Oh, and the Spring error messages:
WARNING: No mapping found for HTTP request with URI [ /index.htm ] in DispatcherServlet with name 'dispatcher'
Apr 22, 2009 10:22:12 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound

Apr 22, 2009 10:24:12 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [ /WEB-INF/views/hello/hello.jsp ] in DispatcherServlet with name 'dispatcher'
Reply cheolho
10:26 PM on April 22, 2009 
Yes this is the same issue I was having. If for example you view the PetShop Clinic in spring they use the path default /static/* meant for static files, images, js, css.. etc. This will work on tomcat but jetty is no good. Ill write up the solution and let you know.
Reply Oleg
4:35 PM on April 28, 2009 
To solve the mapping issue try mapping filter to /* path and explicitly dispatch from filter to servlet cfg.getServletContext().getNamedDispatcher("dispatcher").forward(
req, resp); Don't forget to remove servlet-mapping from web.xml as well.
Reply ramesh
5:28 AM on May 27, 2009 
Hi, I have upgraded my project with spring.3.0.0M2 and I am getting the below error. Can u please guide me to solve this error? Even I have spring.core package in my dependancy.
java.lang.NoClassDefFoundError: org/springframework/core/type/classreading/AnnotationMetadataRead
ingVisitor
Reply Ildar
9:47 AM on June 10, 2009 
Idris says...
Oh, and the Spring error messages:
WARNING: No mapping found for HTTP request with URI [ /index.htm ] in DispatcherServlet with name 'dispatcher'
Apr 22, 2009 10:22:12 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound

Apr 22, 2009 10:24:12 PM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [ /WEB-INF/views/hello/hello.jsp ] in DispatcherServlet with name 'dispatcher'


I've use IntelliJIdea, run you project and get
06-10 06:43AM 58.535
javax.servlet.ServletContext log: Initializing Spring FrameworkServlet 'dispatcher'
W 06-10 06:44AM 00.138
org.springframework.web.servlet.DispatcherServlet noHandlerFound: No mapping found for HTTP request with URI [/] in DispatcherServlet with name 'dispatcher'

something incorect with web.xml?
Reply Max Harper
9:09 AM on June 18, 2009 
To fix the dispatcher problem, see http://blog.newsplore.com/?p=773

Short answer: get rid of the asterisk in the /* url-pattern. This works locally; not confirmed on a live AppEngine instance yet.

BTW - thanks for the great post.
Reply cheolho
6:40 PM on June 18, 2009 
concerning static mapping, on GAE hosted mode, and dev , you can check out my solution here - http://bit.ly/y6xf7 .. i created my own servlet to serve content with links to support why I did it. Also wrote about solution for json view.
Reply Dan
5:34 PM on August 14, 2009 
Thanks for the post.

How did you choose which jars to include? There are many more in the package.
Reply Idris
8:24 PM on August 14, 2009 
@Dan: Choosing the jars was the hard part.. Using all the jars didn't work, so I started with core and kept adding necessary jars until it compiled and worked. In other words, the work is already cut out for you :)
Reply Renegourley
2:35 AM on March 20, 2010 
Max Harper says...
Short answer: get rid of the asterisk in the /* url-pattern. This works locally; not confirmed on a live AppEngine instance yet.

This was a golden comment. Thanks!
Reply Sarath
3:28 PM on March 29, 2010 
1.3.2 is released any updated retest?
Reply Cecile
9:51 PM on April 3, 2010 
This is an amazing site I came here last month and I'm seeing improvement presently keep the good work going and my friends and I will be back soon.
Cecile from macintosh file recovery
Reply Paul
7:13 AM on April 30, 2010 
Thanks for the detailed guide. But how to fix the error by ramesh. Thanks from virtual villagers 4.
Reply Martin
12:14 PM on May 15, 2010 
Thanks for the code. I'm new and useful article for me. I would rate it so - 9 / 10. My crazy taxi
Reply Nice
3:50 AM on June 23, 2010 
Bonjour et merci pour les information bonne continuation pronostic cameroun pays bas
Reply Steven Francolla
7:57 PM on September 28, 2010 
Updated it for Spring 3.0.4. Think it was just some package diffs.

http://github.com/sfrancolla/gae-spring-test
Reply Steven Francolla
7:57 PM on September 28, 2010 
Updated it for Spring 3.0.4. Think it was just some package diffs.

http://github.com/sfrancolla/gae-spring-test
Reply Pierre
3:18 PM on October 8, 2010 
I was forced to download xalan to make it work ! (Spring 3.0.4 + GAE 1.3.7)
( url: http://www.apache.org/dyn/closer.cgi/xml/xalan-j )