Tuesday, April 21, 2009

Further steps: Scala/GWT/App Engine/Eclipse

I've been excited about Scala recently, for a number of reasons -- it's a modern language with lots of great features that you might expect if you've been looking at Haskell or ML. It's got pattern matching, a concise syntax, type inference, and first-order functions. The really killer thing about Scala, though, is how well it integrates with Java.

You can very easily have a mixed Scala and Java project, and make calls back and forth; Scala and Java packages sit in the same package hierarchy and compile to the same bytecode -- it all just works, pretty much seamlessly.

So, clearly, the right thing to do is hook Scala up to GWT RPC and run it on App Engine. Let's do that. This is as awesome as it's going to get, at least until the GWT compiler supports Scala and we can do our client side in Scala too.

I assume you've already installed both the Google Pluin for Eclipse and the Scala IDE for Eclipse. I'm using Eclipse 3.4.

Make a new "Web Application" project (with File > New, or just click the blue "g" icon). Click the boxes for both "Google Web Toolkit" and "App Engine" -- our client side will be in GWT, and the server on App Engine.

Right now, our new project has "Java" nature, but not the "Scala" nature. Add Scala by right-clicking the project and choosing Scala > Add Scala Nature. We're also going to make sure we have a copy of the Scala runtime library once we deploy to the server. Find out where scala-library.jar sits (expand out the "Scala Library" container in your project) and copy it into the project's war/WEB-INF/lib.

Now, down to business. There's a RemoteServiceServlet currently implemented in Java, and we're going to replace it with Scala code -- this is the thing that gets called on the server side when the client makes an RPC request. Find GreetingServiceImpl.java and delete it.

To replace it with a class implemented in Scala, right-click your "gwtscalademo.server" package and select New > Other > Scala Wizards > Scala Class. The class we deleted was a servlet and referenced by the web.xml, so give the Scala class the same name: GreetingServiceImpl.

Here's my version:
package gwtscalademo.server
import gwtscalademo.client.GreetingService
import com.google.gwt.user.server.rpc.RemoteServiceServlet

class GreetingServiceImpl
extends RemoteServiceServlet
with GreetingService {
def greetServer(input:String):String = {
return "Hello from Scala, " + input + "!"
}
}

Note that while in Java, we'd have said implements, in Scala we say with. As I understand it, this means that Java interfaces get mapped onto Scala traits. Hip!

Now you should be able to run the app locally -- right-click your project and select Run As > Web Application. Once you've learned Scala and made it do something interesting (you're on your own there), you can deploy it to App Engine!

Woo!

10 comments:

Tom said...

Hello :)

I followed your instruction precisely, but for some reason when I ran the webapp it was still starting the old Java version.
So I deleted the .class file and tried recompiling, but the .scala is not compiled. I only get ClassNotFound errors when I start it.

Am I doing something wrong ( Eclipse 3.4 and everything uptodate)

Cheers,

- Tom -

Tom said...

Sorry, I had to clean my project first.(I am dirrty and I don't know enough about eclipse ;)

Now it works! Thanks a lot!

Do you also know how to integrate the Lift webframework?

Tom said...

Hmm, I have to clean everytime I change something :(

That can't be right, right :) ?

Alex Rudnick said...

Tom: it really can't be right. But then again, the Scala plugin could use some work -- I expect it'll get more stable in the near future. I honestly find it pretty flaky right now.

I haven't tried Lift yet! But I think there are instructions out there for how to get it going on App Engine...

Germán said...

I didn't know you had to copy scala-library.jar manually! I was getting the dreaded error 500 without logs.
Thanks!!!

Tom said...

Yes Germán, this was really helpful. I wish someone would make such a good "tutorial" for Lift+GAE.
Because it is way trickier than just Scala.

Eishay Smith said...

Anyone knows when GWT will support Scala?

Alex Rudnick said...

Eishay: GWT doesn't have plans (right now) for adding more languages.

Scala to JavaScript would be really cool, and many of the GWT team are Scala fans, but it's not on the roadmap as far as I know.

Patches and side-projects welcome, of course :)

Anonymous said...

They really should have JVM bytecode to Javascript cross compiler.

http://ejohn.org/blog/running-java-in-javascript/

Alex Rudnick said...

@Anonymous: Some really clever people on the GWT team have had that debate.

http://blog.lexspoon.org/2009/10/one-place-you-need-java-source-code.html

http://groups.google.com/group/google-appengine/browse_thread/thread/42c08ca4a6f23891

But! Lex Spoon has started moving with making GWT able to compile Scala.

http://scalagwt.gogoego.com/index.html