Getting started with Google App Engine Java SDK

A few days ago, I tried to use the App Engine Eclipse plugin, but ran into some issues, as described in an earlier post. These were probably due to my lack of experience with Java, Eclipse, and/or the AppEngine dev model, but I was blocked all the same. This time, I’ll start at a lower level, with the App Engine Java SDK.

My first stop was the App Engine Java overview page, which suggests “… you haven’t already, see the Java Getting Started Guide …”, so I hopped over.

The steps outlined in Installing the Java SDK worked well, and I was able to launch the dev server.

Next, I created my first project, the Guestbook app. The steps here were helpful too, and I was able to compile the app successfully (via the Using Apache Ant documentation), but I ran into trouble when I tried to run it:

$ ant runserver
Unable to find a $JAVA_HOME at "/usr", continuing with system-provided Java...
Buildfile: build.xml

copyjars:

compile:

runserver:
[java] 2010-10-14 00:47:18.489 java[24218:903] [Java CocoaComponent compatibility mode]: Enabled
[java] 2010-10-14 00:47:18.492 java[24218:903] [Java CocoaComponent compatibility mode]: Setting timeout for SWT to 0.100000
[java] Oct 14, 2010 7:47:20 AM com.google.apphosting.utils.jetty.JettyLogger info
[java] INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
[java] Oct 14, 2010 7:47:20 AM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
[java] SEVERE: Received exception processing /Users/foo/Sites/appengine/Guestbook/war/WEB-INF/appengine-web.xml
[java] com.google.apphosting.utils.config.AppEngineConfigException: Could not locate /Users/foo/Sites/appengine/Guestbook/war/WEB-INF/appengine-web.xml
...

BUILD SUCCESSFUL
Total time: 3 seconds

The missing file is located in /Users/foo/Sites/appengine/Guestbook/war/WEB-INF/classes/WEB-INF/appengine-web.xml, which seems to be intentional given the statement “All other files found in src/, such as the META-INF/ directory, are copied verbatim to war/WEB-INF/classes/”.

If I add the following to build.xml, so appengine-web.xml and web.xml are coped into the src/WEB-INF dir, then it works:

    <copy todir="war/WEB-INF">
      <fileset dir="src/WEB-INF">
      </fileset>
    </copy>

The next step would be to Using the Users Service, but it’s getting alte, and I’z getting seelpy, so I’ll save that for another day.

To conclude w/ something uplifting, here’s a pic of a sleeping hedgehog.

Sleepy Hedgehog
Sleepy Hedgehog, credit: Andreas-photography

Getting started with Google Eclipse plugin

This post is a record of my first experience with Google’s plugin for Eclipse Helios (3.6)

First impression: anyone who can get Eclipse to install a plugin without multiple errors deserves commendation. Good job, Google.

Doh! Spoke too soon. After running step 5 in the Creating a Project section of the plugin documentation I got “The project cannot be built until build path errors are resolved … Unknown Java Problem”

Sigh. Ok. Searching Stack Overflow … OMG. I can’t believe Eclipse has been around as long as it has and it’s still simply un-runnable. Maybe it’s a Java thing. Searching … “Build path entry is missing: org.eclipse.jdt.launching.JRE_CONTAINER” … Wow. A couple hours later and no luck.

Back to Ruby for a little pick-me-up 🙂

update (Oct. 15)

A friend with more experience helped me sort this out:

  1. Find your JDK.  On Mac, 10.6 it’s in /System/Library/Frameworks/JavaVM.framework
  2. In Eclipse menu bar, go to Eclipse > Preferences… > Java > Installed JREs
  3. Click “Add…”
  4. Either click “Directory…” and browse to the location of the JDK from step 1, or just enter the path if you know it.  In my case, it was
    /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/
  5. Give it a name.  Mine is “JDK 6”
  6. Click OK to save

Before trying again with the Google Eclipse plugin, I ran the software update (Help > Check for Updates) and restarted, for good luck.

App Engine Y!AP app that pushes updates via OpenSocial JS API

Usage:

  1. create App Engine app
  2. edit main.py to look like the code below and deploy
  3. create YAP app
  4. set app base url to yourappname.appspot.com/example
  5. preview your app
import wsgiref.handlers
from google.appengine.ext import webapp

class ExampleHandler(webapp.RequestHandler):
	def post(self):
		html = """
		
		//ref: http://developer.yahoo.com/yap/guide/opensocial-examples.html
		var postActivity = function(title, body) {
				var params = {};
				params[opensocial.Activity.Field.TITLE] = title;
				params[opensocial.Activity.Field.BODY] = body;
				var activity = opensocial.newActivity(params);
				opensocial.requestCreateActivity(
					activity,
					opensocial.CreateActivityPriority.LOW,
					function(){});
			},
			handleResponse = function(response){

				var viewer = response.get('viewer').getData(),
					name = viewer.getDisplayName();

				postActivity(
					name + ' posted an update ...',
					'... using OpenSocial!'
				);
			},
			getViewerData = function() {
				var req = opensocial.newDataRequest();
			  	req.add(req.newFetchPersonRequest("VIEWER"), "viewer");
				req.send(handleResponse);
			};

		//this is the bare minimum code to push updates
		var params = {};
		params[opensocial.Activity.Field.TITLE] = 'title';
		params[opensocial.Activity.Field.BODY] = 'body';
		var activity = opensocial.newActivity(params);
		opensocial.requestCreateActivity(
			activity,
			opensocial.CreateActivityPriority.LOW,
			function(){});

		//this is a slightly enhanced update flow
		getViewerData();

		
		"""
		self.response.headers['Content-Type'] = 'text/html'
		self.response.out.write(html)

application = webapp.WSGIApplication(
	[('/example', ExampleHandler)],
	debug=True)

def main():
	wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
 main()

AppEngine unconference

free, scalable hosts:
-joyant/sun
-amazon
-appengine
— free up to 5m page views per mo

–enforces constraints optimized for scalability

—python

—BigTable

—GQL

–features

—memcache

—WSGI-compliant

—uses the same cloud-access points as are available within Google

–moving forward

—map appengine SDK to hadoop