k4200’s notes and thoughts

Programmer side of k4200

Play! + Scala on GAE

I attended a study session about Play! Framework in Osaka. Actually, I hadn't used it, but most of the sessions were for beginners, and quite useful for me. After the sessions finished, we had two hours of free time and everybody did what he liked. Reading books, talking about Play, just chit-chatting etc. I was trying to get a Play app in Scala running on Google App Engine (GAE), and finally succeeded.

I'll write about the steps that I took and also some pitfalls that I experienced. This entry is for beginners who are interested in Play! framework and Scala.

Environment

My environment was as follows:

Play! 1.2.2 + Scala module 0.9.1 didn't work (for me) on GAE

At first, I tried Play! 1.2.2 + Scala module 0.9.1, which are the latest as of this writing, but couldn't get them working, so I switched to Play! 1.2.1 + Scala module 0.9 and now everything seems okay.

Steps

Here are the steps that I took.

Install Play! framework

Download the zip package of Play! and unzip it. Then add /play to your PATH environment variable. I also set PLAY_HOME to the unzipped directory.

Install Google App Engine SDK for Java

The guy that had given a presentation about Play on GAE told me that it's not necessary to install GAE SDK for Java, but apparently it is. (Or, maybe I just misunderstood what he had said.)

To install it, download the package, unzip it and set GAE_PATH to the directory.

Install modules

Play! framework's modules are like plugins. We need to install GAE and Play Scala modules by the following commands:

$ play install scala-0.9
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2.1, http://www.playframework.org
~
~ Will install scala-0.9
~ This module is compatible with: 1.2
~ Do you want to install this version (y/n)? y
~ Installing module scala-0.9...
~
~ Fetching http://www.playframework.org/modules/scala-0.9.zip
~ [--------------------------100%-------------------------] 18785.9 KiB/s    
~ Unzipping...
~
~ Module scala-0.9 is installed!
~ You can now use it by adding it to the dependencies.yml file:
~
~ require:
~     play -> scala 0.9
~
$ play install gae
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2.1, http://www.playframework.org
~
~ Will install gae-1.4
~ This module is compatible with: 1.1, and GAE 1.4.0
~ Do you want to install this version (y/n)? y
~ Installing module gae-1.4...
~
~ Fetching http://www.playframework.org/modules/gae-1.4.zip
~ [--------------------------100%-------------------------] 18187.5 KiB/s   
~ Unzipping...
~
~ Module gae-1.4 is installed!
~ You can now use it by adding it to the dependencies.yml file:
~
~ require:
~     play -> gae 1.4

You may notice a message about dependencies.yml. We'll do that later.

Create a Play project

Now, we're ready to create a project. Creating a project is easy. Don't forget to add "--with scala". We don't want to write Java code anymore.

$ play new projectfoo --with scala
Module dependencies

As I wrote above, we need to write module dependencies in /conf/dependencies.yml. I added the last line for the GAE module.

# Application dependencies

require:
    - play
    - play -> scala 0.9.1
    - play -> gae 1.4

Then, I executed the following command. I'm not sure what it does actually (will check).

$ play dependencies --sync
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2.1, http://www.playframework.org
~
~ Resolving dependencies using /Users/k4200/projectfoo/conf/dependencies.yml,
~
~ 	play->scala 0.9 (from playLocalModules)
~ 	play->gae 1.4 (from playLocalModules)
~
~ Some dependencies have been evicted,
~
~	play 1.2 is overriden by play 1.2.1
~
~ Installing resolved dependencies,
~
~ 	modules/scala-0.9 -> /Users/k4200/programs/play-1.2.1/modules/scala-0.9
~ 	modules/gae-1.4 -> /Users/k4200/programs/play-1.2.2/modules/gae-1.4
~
~ Done!
~
Create an application on GAE

Create an application on GAE. The application name doesn't have to be the same as the project name ("projectfoo" in this case).

Edit appengine-web.xml

Almost there. We need to tie the Play! project (projectfoo) with the app on GAE. This information should be defined in appengine-web.xml, which doesn't exist at first.

The following command starts the app on the local environment and creates the file. After the app is started, you can quit it by Ctrl + C.

$ play run
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! 1.2.1, http://www.playframework.org
~
~ Ctrl+C to stop
~ 
Listening for transport dt_socket at address: 8000
17:45:29,443 INFO  ~ Starting /Users/k4200/workspace/projectfoo
17:45:29,446 INFO  ~ Module gae is available (/Users/k4200/programs/play-1.2.2/modules/gae-1.4)
17:45:29,447 INFO  ~ Module scala is available (/Users/k4200/programs/play-1.2.1/modules/scala-0.9)
17:45:30,070 WARN  ~ 
17:45:30,070 WARN  ~ Google App Engine module
17:45:30,070 WARN  ~ ~~~~~~~~~~~~~~~~~~~~~~~
17:45:30,070 WARN  ~ No Google App Engine environment found. Setting up a development environement
17:45:30,080 WARN  ~ Don't forget to define your GAE application id in the 'war/WEB-INF/appengine-web.xml' file
17:45:30,080 WARN  ~ 
17:45:30,080 INFO  ~ Detected that plugin 'play.modules.gae.GAEPlugin@6708f8e0' disabled the plugin 'play.jobs.JobsPlugin@53dafbaf' the old way - should use Play.disablePlugin()
17:45:30,797 WARN  ~ You're running Play! in DEV mode
17:45:30,862 INFO  ~ Listening for HTTP on port 9000 (Waiting a first request to start) ...
17:45:47,762 INFO  ~ Application 'projectfoo' is now started !
^C~ ...

Then edit the file. It should look like the following. "gaetestfoo" is the name of the application on GAE, which is different from the project name "projectfoo".

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
	<application>gaetestfoo</application>
	<version>1</version>
</appengine-web-app>
Deploy

Now, you can deploy the app by the following command. First time you do this, you'll be asked your Gmail account and password.

$ play gae:deploy

That's it. Open up a browser window and access the URL, and hopefully you'll see the index page.

Errors

I encountered several errors before getting the app running. I'll write those error messages and solutions/workarounds here.

GAE SDK isn't installed

You need to install GAE SDK for Java as I mentioned above. If you don't, you'll see the error below when deploying:

~ You need to specify the path of you GAE installation, 
~ either using the $GAE_PATH environment variable or with the --gae option
400 Bad Request

This happened when I forgot to modify appengine-web.xml.

java.io.IOException: Error posting to URL: https://appengine.google.com/api/appversion/create?app_id=&version=1&
400 Bad Request
app_id GET query string parameter must be supplied.

Unable to update app: Error posting to URL: https://appengine.google.com/api/appversion/create?app_id=&version=1&
400 Bad Request
app_id GET query string parameter must be supplied.
Cannot load jar

The following exception occurred when I was trying Play 1.2.2 and Play Scala module 0.9.1. After switching to Play 1.2.1 and Scala module 0.9, the error disappered.

play.Logger niceThrowable: Cannot load jar:file:/base/data/home/apps/s~gaetestfoo/1.35235236581793114/WEB-INF/lib/play-scala.jar!/play.plugins
java.lang.NullPointerException
	at play.scalasupport.ScalaPlugin.<init>(ScalaPlugin.scala:166)
	at java.lang.Class.newInstance0(Class.java:372)
	at java.lang.Class.newInstance(Class.java:325)
	at play.plugins.PluginCollection.loadPlugins(PluginCollection.java:100)
	at play.Play.init(Play.java:286)
	at play.server.ServletWrapper.contextInitialized(ServletWrapper.java:74)
	at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
	at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
	at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
	at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
	at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
	at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.createHandler(AppVersionHandlerMap.java:202)
	at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:171)
	at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:123)
	at com.google.apphosting.runtime.JavaRuntime.handleRequest(JavaRuntime.java:260)
	at com.google.apphosting.base.RuntimePb$EvaluationRuntime$2.handleRequest(RuntimePb.java:9805)
	at com.google.net.rpc.impl.RpcUtil.runRpcInApplication(RpcUtil.java:422)
	at com.google.net.rpc.impl.Server$RpcTask.runInContext(Server.java:579)
	at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:449)
	at com.google.tracing.TraceContext.runInContext(TraceContext.java:689)
	at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:327)
	at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:319)
	at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:447)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:636)


I'm not sure this is a bug that affects other people, or an issue specific to my environment. I'll look into this when I have time, and send a bug report if need be.

Eclipse

If you want to play around with Play! framework in Scala, I would recommend you start with command line and a text editor, and not use Eclipse until you are used to the basics of Play! framework.

Here are some basics to understand when you use Eclipse with Play! framework in Scala.

play eclipsify

The following command creates .project file for Eclipse.

$ play eclipsify

Then, you need to import the created project into Eclipse.

You might encounter the following error on Eclipse. This happens when the Scala library isn't included in your project.

Error in Scala compiler: typeConstructor inapplicable for <none>

Usually, you're prompted to add it to your project and thus don't see it.

Configure the build path

After creating a project and starting Eclipse, it complains about compilation shown below. However, if you access http://localhost:9000/ , the page shows up successfully.

object Application is not a member of package views

I found a thread about the problem and workaround on StackOverflow. Adding tmp/generated to you Build Path solves the issue.
http://stackoverflow.com/questions/6177851/errors-in-eclipse-for-scala-project-generated-by-play-framework

Conclusion(?)

Personally, I like Lift and have used it for several months now. One of the advantages of Play over Lift is it has good documentation. And, as far as I see from the documentation, Play seems pretty powerful yet easy to start. Also, GAE is a great platform, so combination of Play, Scala and GAE should be fantastic. Yes, it should be.

But, the problem is there's not a lot of information about the combination, or real-world production experiences using them. If I were to use Play for a real product or service, I wouldn't choose GAE. EC2 (or other cloud services) are more straight forward and less trouble in terms of development.

In Scala world, there are some other frameworks than Lift and Play that have come out recently. Exciting, isn't it? Since there's no "best" framework in Scala at this moment, I'll keep watching them for now and choose an appropriate one on a case-by-case basis.