Getting started with Stripes & Google App Engine

This is a basic example of using Stripes Framework with the cloud infrastructure of Google. I am using Stripes in one of my projects that I am thinking to move it to google app engine so I decided to experiment before the migration. More posts will follow in this topic as I progress with it. The first objective is to create the basic project structure, configure and deploy, well… a hello world web application. This is a trivial application but there are some limitations using google app engine so trying to use the framework as is will fail with some non-sense stack traces.

The following is a list of things that we will be need to complete this application:
1. Stripes Framework (home page: http://www.stripesframework.org/display/stripes/Home )
2. Google app engine sdk – if you use eclipse and google plugin the sdk is included in the plugin.
3. Eclipse (you can use whatever IDE or environment you like, it’s not mandatory to use eclipse, it’s just easier).

Note: For information on how to install the google plugin visit http://code.google.com/appengine/docs/java/tools/eclipse.html

I assume you are familiar with java web frameworks and that you will use eclipse with the google plugin.

The first step is to create a project in the eclipse IDE:

Give a name to the project and an initial package name. For the moment we do not need GWT so just deselect it.

After pressing finish we have the following project structure.

Before continuing copy the Stripes jars in the the lib directory under hello_project/web/WEB_INF/lib and add them to the project’s build path by selecting them, right click-> Build Path -> Add to Build Path. Also copy and paste the StripesResources.properties in the directory “src” (not in a package).

By default the google plugin will generate a servlet for us, under the package name that we entered in the previews step. It will also generate the following configuration files:
Servlet spec requirement:
1. web.xml (this is the well known deployment descriptor required by the servlet specification)

Google App engine specific (we will not use them for this application):
1. appengine-web.xml
2. jdoconfig.xml

Logging property files:
1. log4j.properties
2. logging.properties

For the purpose of this trivial application we will only need to edit the web.xml (a.k.a Deployment Descriptor so from know on I will call it DD).
By default the plugin registers the generated servlet in the DD, so open the DD and delete the servlet and servlet-mapping it’s not needed.

The following is the generated DD that need to be edited:

The following is the new and final DD containing the Stripes filter and dispatcher servlet:

Note that the web-app tag version has changed from 2.5 to 2.4 there are some jsp exceptions with the 2.5.

The Stripes filter includes two initial parameters the ActionResolver.Packages which tells Stripes where to find the ActionBeans (more on this in next post or in Stripes documentation) and the MultipartWrapperFactory.Class, a factory class used to upload files, but uploading files is not supported by google app engine and the Stripes filter will fail to initialize. Therefore we need to disable this by providing an empty configuration.

The first step to disable file uploading is to add MultipartWrapperFactory.Class initial parameter to the Stripes filter as shown in the DD and the second step is to create the appropriate class. So create a package in the project (I created the com.helloworld.exclude but you can create anything that make sense for your project) and add the following class:


import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import net.sourceforge.stripes.config.Configuration;
import net.sourceforge.stripes.controller.FileUploadLimitExceededException;
import net.sourceforge.stripes.controller.multipart.MultipartWrapper;
import net.sourceforge.stripes.config.ConfigurableComponent;
import net.sourceforge.stripes.controller.multipart.MultipartWrapperFactory;

/**
 * GAE does not support file uploading so we need to disable this feature from Stripes.
 *
 * @author 110j
 */
public class EmptyMultipartWapper implements ConfigurableComponent, MultipartWrapperFactory {

	/**
	 * @see net.sourceforge.stripes.config.ConfigurableComponent#init(net.sourceforge.stripes.config.Configuration)
	 */
	public void init(Configuration conf) throws Exception {
	}

	/**
	 * @see net.sourceforge.stripes.controller.multipart.MultipartWrapperFactory#wrap(javax.servlet.http.HttpServletRequest)
	 */
	public MultipartWrapper wrap(HttpServletRequest request) throws IOException, FileUploadLimitExceededException {
		return null;
	}
}

Now that we disabled the file uploading lets create an ActionBean that will handle our request. Create a package in the project called com.helloworld.action and add the following class:


package com.helloworld.action;

import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;

/**
 * The action bean that will handle the our simple request.
 *
 * @author 110j
 */
public class EasyActionBean implements ActionBean {
	private static final String VIEW = "/WEB-INF/jsp/hello_world.jsp";
	private static final String MY_MESSAGE = "hello world";
	private ActionBeanContext ctx;

	private String message;

	@DefaultHandler
	public Resolution showMe() {
		this.setMessage(MY_MESSAGE);
		return new ForwardResolution(VIEW);
	}

	/**
	 * @see net.sourceforge.stripes.action.ActionBean#getContext()
	 */
	public ActionBeanContext getContext() {
		return this.ctx;
	}

	/**
	 * @see net.sourceforge.stripes.action.ActionBean#setContext(ActionBeanContext)
	 */
	public void setContext(ActionBeanContext ctx) {
		this.ctx = ctx;
	}

	/**
	 * @return the message
	 */
	public String getMessage() {
		return message;
	}

	/**
	 * @param message the message to set
	 */
	public void setMessage(String message) {
		this.message = message;
	}
}

Next lets create a jsp file that will render the response, create the hello_world.jsp under WEB_INF/jsp/ and add the following content:

Finally create a welcome file called index.jsp if it does not exist or rename the index.html to index.jsp and add just a forward to the action:

You can delete the servlet generated by the google plugin there is no need for it.

In order to test it you just need to run the hello_world in the Run history of eclipse as the google plugin will create one for us, or under the run button in the toolbar, and then visit the address localhost:8080

NOTE: if your application require session you need to enable it in the appengine-web.xml since it is disabled by default (but keep in mind the implication it may have in a distributed environment such as google app engine, maybe your attributes will need to implement the HttpSessionActivationListener if you plan to add them in the session).

You can upload your application by using eclipse or the command line tool, for more information visit http://code.google.com/appengine/docs/java/gettingstarted/uploading.html

To be continued!

Advertisements

14 thoughts on “Getting started with Stripes & Google App Engine

  1. Pingback: Redoing Guestbook example with Stripes « 110j

  2. Pingback: The Stripes framework « 110j

  3. Hello, Thanks for the tutorial, it was really helpful. But I wanted to point out a few typos that tripped me up along the way.
    1. In your web.xml you missed the r in EmptyMultipartWrapper, you spelt it Wapper instead. Same goes for the class.
    2. You don’t need the double quotation marks after ${actionbean.message}
    3. it needs to be ${actionBean.message} with a capital B

  4. I must apologize, but I’m having problems getting the initial requests working, you seem to have missed a few steps for the ultra newbies (ones new to java, anyway). I go to Run As -> Web Application, and where do you place the jsp files? I put the index.jsp where the index.html was (in the root of web-inf), but still no go. Server doesn’t seem to accept the request and forward it to the correct location, just keep getting 404s.

    Thanks for any help you can provide :)

    • when you create an app engine project in eclipse there is a launch shortcut, so you need to use that one instead of run as web application, that will start an agent that app engine needs.

      I suggest that you first run app engine without stripes following the examples google provides and once you understand the process then it will be easy to use stripes with it…

      • Yeah I was able to set it up without, and started building an app before realizing that JSPs and affiliated technology are a little unwieldy without a decent framework, which is why I stumbled upon stripes. Good advice though, perhaps I should play more before moving to Stripes.

      • Finally figured out what the problem was… The application was expecting the commons-logging jar file within the lib directory. Once I added that it ran fine. Onto coding! :D

        Thanks for your tutorial mate, greatly appreciated!

  5. Sorry! I didn’t noticed before but if you put your jsp inside the web-inf then they are not accessible. The only way to access them is through an action bean.

    If you want to access them directly then put them in the same level with WEB-INF, not inside.

    hope that helps…

  6. I have followed this blog and tried to run Calculator from Stripes website. Everything seems working except the jsp page doesn’t show the result. It still display ${actionBean.result}, do you have any idea why? I have debugged into the addition method and the method did return a ForwardResolution. I am running in Eclipse. There was no error in log. Thanks

      • Brilliant. It works right now. what I had before was for version 2.5 which was generated by Eclipse with App Engine SDK plugin.

        Why ${actionBean.result} doesn’t work with the version 2.5?

        Thanks
        -Jianfei

      • It works with any schema version! but you would need to add the standard.jar and jstl.jar into the lib folder, keep in mind that there are some compilation errors sometimes, I was too busy to find out why… but I suspect it has to do with the version of the jar file that I used, give it a try, just for fun!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s