Popstat on Google App Engine
Popstat is the demo application from my Facebook Dev Garage Dallas presentation. It just posts a status message to Facebook and Twitter to demonstrate using both Facebook Connect and an external service. I developed it on my laptop and didn't have time to move it to a public host before the event. I wanted it out there live someplace and figured it was a good opportunity to try out Google App Engine's Java support (Popstat uses Grails with a mix of Groovy and Java)
I got it all working, but it was a pain.
- I used the Grails AppEngine plugin. I liked it.
- App Engine provides storage, but not in the form of a relational database. It's close enough that JPA and JDO both work (but not Hibernate, yet). I chose JPA, but either way you'll need to annotate your domain classes (I expected the GORM-JPA plugin to do that for me, but it didn't)
- You'll need to put your domain classes into named packages. Things (silently) don't go well if you leave them in the default package.
- If you're using JPA, domain classes will need to explicitly declare an id field. Make it a Long, and add the @Id and @GeneratedValue annotations. Use GenerationType.IDENTITY.
- I was able to use the dynamic save() method provided by GORM-JPA, but I had to wrap up the calls in a withTransaction block, and the semantics are slightly different (use merge() instead of save() for updates)
- Depending on your version of Spring, you may get a message along the lines of "org.springframework. context.annotation. internalPersistenceAnnotationProcessor': Initialization of bean failed" with something about "java.lang.NoClassDefFoundError: javax/naming/NamingException". The fix here worked for me.
- Popstat uses the facebook-java-api library. Since App Engine forbids the use of JAXB, I had to switch to the JSON version of the client to avoid an error about JAXBContext.
- To talk to Twitter, Popstat uses the oauth-signpost library. But Signpost depends on Apache HttpClient, and HttpClient uses low-level Socket calls forbidden by App Engine. I hacked Signpost to use URLConnection, but I wouldn't recommend that approach. If I had to do it again, I'd look around for an OAuth library that worked out of the box.
- By default, the App Engine Java Development Server (a version of the App Engine environment you can run on your local machine) binds to localhost only. The command line client has a "--address" option, but the "grails app-engine run" command doesn't. I hacked the scripts/AppEngine.groovy plugin and harcoded the address parameter into startDevServer().
Overall, though, it wasn't a great experience. Google turns off random bits of Java (for security and ease of management), which means that very few third-party libraries are going to work. You'll probably have to do some porting of your own code as well. That, combined with the admin service being down all morning, left a bad taste. The free hosting thing is great for demo apps but I think I'll stick to something like Amazon EC2 for real work. I'm very curious to see how Microsoft Azure stacks up (it's much more of a direct competitor to App Engine than the roll-it-all-yourself EC2)
You should follow me on twitter here.
8 Comments:
Hi, I am also attempting a GAE + Grails experiment along the same lines as yours. I ran across the referenced fix you mention for the NamingException issue (i.e., installing a fake internalPersistenceAnnotationProcessor) but have had little luck with it. Did you simply add your bean definition to the existing resources.groovy file?
I used conf/spring/resources.xml:
<beans>
<bean id="org.springframework.context.annotation.internalPersistenceAnnotationProcessor"
class="com.praxisbridge.popstat.GaeFixInternalPersistenceAnnotationProcessor" />
</beans>
Oh, and I sometimes (but not always) get this:
http://www.nabble.com/app-engine-plugin-and-entityManagerFactory-(double-creation-causes--failure)-td24245287.html
Hmm.. I still get the NamingException. I have tried putting the bean declaration in resources.groovy, resources.xml and even directly into the WEB-INF/applicationContext.xml file. I must be hosing something somewhere....
ignore my last post. I was deploying the wrong app profile. heh. FWIW, I could only get the bean declaration to work in resources.xml and not in resources.groovy.
I am now experiencing the double creation error. Onward and upward!
Thanks for your help. I will chime in with updates/progress
Ok, updating to version 0.8.3 of the AppEngine plugin seems to have helped with the double creation error referenced earlier. I want to do a little more testing, then I'll update the blog post with an addendum...
Yeah I also updated both the gorm-jpa plugin and the app-engine plugin the other day, but its something of a 'two steps forward, one step back' mode of progress.
I am still having great difficulties managing even the most basic of 1-N relationships, regardless of the persistence API I choose (I have gone back and forth between JPA and JDO). Everytime I think I am getting closer, I hit another roadblock. Not sure how much more stamina I have.
This is incredible I got excellent things in here thongs I had never read, it has been really helpful for me thanks so much.
Post a Comment
<< Home