jruby on appengine
DESCRIPTION
A meetup talk given at budapest.rb http://www.meetup.com/budapest-rb/TRANSCRIPT
Agenda
JVM
Scripting on the JVM
JRuby
Rack
Google AppEngine/Java
Experiences
JVM
Java Language != Java Platform
Platform Independence
Rich Class System
Open Source
JVM
Java Runtime Environment
JVM JVM JVM
App App App
JVM
Fine tuneability
Extensibility
Stable
Admin interfaces
Safe code sharing
Scripting on the JVM
Python (Jython - http://www.jython.org)
Ruby (JRuby - http://www.jruby.org)
Lisp (Clojure - http://clojure.org)
JavaScript (Rhino - http://www.mozilla.org/rhino/)
PHP (IBM - P8 / Caucho - Quercus)
Scala (http://www.scala-lang.org)
And many many more
Scripting on the JVM
How?
Scripting on the JVM
JSR-223
import javax.script.*
http://scripting.dev.java.net/http://developers.sun.com/scripting/
Scripting on the JVM
Java Runtime Environment
JVM
App
Scripting
JRuby
Scripting on the JVM
Why?
Scripting on the JVM
Rapid app development
Special needs, eg. at liligo.com ;)
Integration
JRuby
Ruby for JavaRuby in Java
JRuby
Native Threads
Garbage Collector
Embeddability
No fork
No C extensions
Rack
Rails, Merb, Sinatra, Camping, Ramaze ...
CGI, FCGI, Mongrel, Thin, Webrick, Litespeed ...
Rack
class HelloWorld def call(env) [200, {"Content-Type" => "text/plain"}, ["Hello world!"]] endend
Rack
Simple Ruby API modelling HTTP
Standard interface between frameworks and handlers
Interface for injecting middlewares
Rack
WSGI for Rubyhttp://chneukirchen.org/talks/#introducingrack
http://wiki.github.com/rack/rack
JRuby-Rack
WSGI for JRuby
Rack + Java Servlet ContainersTomcat, Glassfish, Jetty ...
<context-param> <param-name>rackup</param-name> <param-value> require 'rubygems' require 'app' set :environment, :production set :run, false run Sinatra::Application </param-value></context-param> <filter> <filter-name>RackFilter</filter-name> <filter-class>org.jruby.rack.RackFilter</filter-class> </filter> <filter-mapping> <filter-name>RackFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.jruby.rack.RackServletContextListener </listener-class> </listener>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"> <context-param> <param-name>public.root</param-name> <param-value>/</param-value> </context-param> <filter> <filter-name>RackFilter</filter-name> <filter-class> org.jruby.rack.RackFilter </filter-class> </filter> <filter-mapping> <filter-name>RackFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <listener> <listener-class>org.jruby.rack.merb.MerbServletContextListener </listener-class> </listener></web-app>
JRuby-Rack
Java Runtime Environment
JVM
App
FrameworkJRuby
Servlet container
Rack
Google AppEngine/Java
What?
Google AppEngine/Java
App stack
App hosting
Development environment
Great API system
A bunch of services
for free ...
GAE/J – App stack
Automatic scaling
Write your App only
Everything else happens on APIs
External APIs with URL Fetch
GAE/J – App hosting
10 app / google user
Admin interface
Cron
Quota is OK
Logging
GAE/J – App hosting
GAE/J – App hosting
GAE/J – App hosting
GAE/J – Dev environment
App server
Deployment
App versions
Multiple developer accounts
Good examples
SDK
Plugins (Eclipse IDE)
GAE/J – APIs / Services
Memcache
Datastore
Image
Google account
URL Fetch
GAE/J - Datastore
Schemaless
Object oriented
Key / Value
Universal
< Entity ( Story (1) ) >
Experiences
Slow warmup (JRuby + AppEngine)
Nice performance after App cache
CPU intensive operations
Almost unusable Dev tools
Rare libs for GAE/J APIs
No migration (bulk loader is 404!)
Experiences
JRuby-AppEngine (low level wrapper for almost all APIs)
Bumble (minimal lib for the Datastore)
Datamapper (with JRuby-AppEngine)
Warbler (for deployment)
JRuby-AppEngine
post '/story/add' do @story = Datastore::Entity.new('Story') @story['title'] = params[:title] @story['slug'] = params[:slug] @story['body'] = Datastore::Text.new( params[:body] ) Datastore.put(@story) redirect '/stories'end
Bumbleclass Person include Bumble ds :given_name, :sur_name, :email has_many :blogs, Blog, :owner_idend
class Blog include Bumble ds :name, :owner_id, :created_at belongs_to :owner, Person has_many :posts, :Post, :blog_id, :iorder => :created_atend
class Post include Bumble ds :title, :content, :created_at, :blog_id belongs_to :blog, Blogend
Warbler
Warbler::Config.new do |config| config.dirs = %w(lib views models) config.includes = FileList["appengine-web.xml", "app.rb", "config.ru"] config.gems = ['sinatra', 'haml','appengine-apis','maruku'] config.gem_dependencies = true config.war_name = "test" config.webxml.booter = :rack config.webxml.jruby.min.runtimes = 1 config.webxml.jruby.max.runtimes = 1 config.webxml.jruby.init.serial = true config.java_libs = []end
Components
Appengine account
GAE/J SDK
JRuby 1.3.1
JRuby-Rack
Gems
GAE/Merb Example Application ;)http://github.com/yaanno/gae-merb-example
Merb flat app
WEB-INF appengine-web.xml web.xml application.rb config framework.rb init.rb lib appengine-api-sdk.jar gems.jar jruby-complete.jar jruby-rack.jar views index.haml
Thanks
A few useful links
http://www.infoq.com/presentations/nicholson-php-jvmhttp://www.artima.com/insidejvm/ed2/index.htmlhttp://code.google.com/appengine/http://blog.headius.comhttp://blog.nicksieger.comhttp://olabini.com/blog/http://isitjruby.com/http://code.google.com/events/io/sessions.html#appengine