Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Standing on the Shoulders of Giants with JRuby

Standing on the Shoulders of Giants with JRuby

Presentation given at Software Passion Summit, March 2012

8c21306523b16ba5dd35c3549bf90994?s=128

Theo Hultberg

April 14, 2012
Tweet

Transcript

  1. STANDING ON THE SHOULDERS OF GIANTS WITH JRUBY måndag 19

    mars 12
  2. Theo @iconara måndag 19 mars 12

  3. Chief Architect at måndag 19 mars 12

  4. måndag 19 mars 12

  5. ruby måndag 19 mars 12

  6. TL;DR Most of you are Java developers Writing Java is

    tedious There’s truckloads of great Java libraries The JVM is awesome Ruby is awesome ∴ JRuby FTW måndag 19 mars 12
  7. I’M NOT HERE TO MAKE FUN OF JAVA just måndag

    19 mars 12
  8. JRuby vs. vanilla Ruby Real threads A working GC Every

    Java, Scala and Ruby library ever made All the JVM awesomeness, JIT, the lot måndag 19 mars 12
  9. JRuby vs. Java It doesn’t make you want to stab

    yourself måndag 19 mars 12
  10. måndag 19 mars 12

  11. JRUBY — JAVA A WHIRLWIND TOUR måndag 19 mars 12

  12. JRuby — Java stuff = TreeMap.new stuff['windmill'] = 'rocket' stuff['pirate']

    = 'bees' stuff.each do |something| # redacted end måndag 19 mars 12
  13. JRuby — Java require 'java' require 'rabbitmq-client.jar' import 'com.rabbitmq.client.ConnectionFactory' factory

    = ConnectionFactory.new() factory.setUri('amqp://localhost:5672/') connection = factory.newConnection() måndag 19 mars 12
  14. JRuby — Java require 'java' require 'rabbitmq-client.jar' import 'com.rabbitmq.client.ConnectionFactory' factory

    = ConnectionFactory.new factory.uri = 'amqp://localhost:5672/' connection = factory.new_connection måndag 19 mars 12
  15. JRuby — Java class Worker < Thread def run puts

    'Hard work, no play' end end # or class Worker include Runnable def run puts 'Hard work, no play' end end måndag 19 mars 12
  16. JRuby — Java pool = Executors.new_fixed_thread_pool(3) memes = LinkedBlockingQueue.new 10.times

    do pool.submit do open('http://api.autome.me/text').read.each_line do |meme| memes << meme end end end pool.shutdown pool.await_termination(3, TimeUnit::DAYS) memes.each { |m| puts(m) } måndag 19 mars 12
  17. JRUBY FOR REPRESSED JAVA DEVELOPERS måndag 19 mars 12

  18. Made up fact 84% of Java devs don’t write tests

    because it’s way too much extra code to type. måndag 19 mars 12
  19. Testing public class Person { public final String firstName; public

    final String lastName; public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFullName() { return String.format("%s %s", firstName, lastName); } // omg I’m already bored } måndag 19 mars 12
  20. Testing class TestPerson < Test::Unit::TestCase def setup @person = Person.new('James',

    'Gosling') end def test_full_name assert_equal('James Gosling', @person.full_name) end end # this is TestUnit, it’s part of the stdlib måndag 19 mars 12
  21. Testing describe Person do describe '#full_name' do before do @person

    = Person.new('James', 'Gosling') end it 'is the first name and the last name with a space in-between' do @person.full_name.should == 'James Gosling' end end end # this is RSpec, read more at rspec.info måndag 19 mars 12
  22. Made up fact Ant was designed by the same people

    who came up with the QWERTY layout. måndag 19 mars 12
  23. Automation <?xml version="1.0"?> <project name="MyProject" default="dist" basedir="."> <description> simple example

    build file </description> <!-- set global properties for this build --> <property name="src" location="src"/> <property name="build" location="build"/> <property name="dist" location="dist"/> <target name="init"> <!-- Create the time stamp --> <tstamp/> <!-- Create the build directory structure used by compile --> <mkdir dir="${build}"/> </target> <target name="compile" depends="init" description="compile the source "> <!-- Compile the java code from ${src} into ${build} --> <javac srcdir="${src}" destdir="${build}"/> </target> <target name="dist" depends="compile" description="generate the distribution"> <!-- Create the distribution directory --> <mkdir dir="${dist}/lib"/> <!-- And don’t get me started on Maven, $%&@*! --> <!-- Put everything in ${build} into the MyProject-${DSTAMP}.jar file --> måndag 19 mars 12
  24. Automation require 'ant' src_dir = 'src' build_dir = 'build' dist_dir

    = 'dist' timestamp = Time.now task :init do mkdir_p build_dir end task :compile => :init do ant.javac :srcdir => src_dir, :destdir => build_dir end task :dist => :compile do mkdir_p "#{dist_dir}/lib" ant.jar :jarfile => "#{dist_dir}/lib/MyProject-#{timestamp}.jar", :basedir => build_dir end task :clean do rm_rf build_dir rm_rf dist_dir måndag 19 mars 12
  25. Made up fact The average number of lines in a

    Java web application is somewhere around 100 000 måndag 19 mars 12
  26. Don’t make it so hard get '/' do erb :index

    end post '/register' do stuff.save(params[:name], params[:email], params[:shoe_size]) redirect '/thanks' end get '/thanks' do @name = params[:name] erb :thanks end # this is Sinatra, read more at sinatrarb.com måndag 19 mars 12
  27. Pack it up in a WAR and ship it $

    warbler war # warbler can be found at github.com/jruby/warbler # also check out torquebox.org, and github.com/trinidad/trinidad måndag 19 mars 12
  28. Make a console $ hbase shell HBase Shell; enter 'help<RETURN>'

    for list of supported commands. Type "exit<RETURN>" to leave the HBase Shell Version 0.90.4-cdh3u2, r, Thu Oct 13 20:32:26 PDT 2011 hbase(main):001:0> create 'test', 'cf' 0 row(s) in 1.2200 seconds hbase(main):002:0> put 'test', 'row1', 'cf:a', 'value1' 0 row(s) in 0.0560 seconds hbase(main):003:0> put 'test', 'row2', 'cf:b', 'value2' 0 row(s) in 0.0370 seconds måndag 19 mars 12
  29. Monitoring require 'jmx' client = JMX.connect(:port => 7199) storage_service =

    client['org.apache.cassandra.db:type=StorageService'] storage_service.keyspaces.each do |keyspace| puts keyspace end memory_mbean = client['java.lang:type=Memory'] puts memory_mbean.heap_memory_usage.used memory_mbean.gc måndag 19 mars 12
  30. Configuration conf = configuration do base_keys :api_key, :date dimension :path

    dimension :section dimension :country dimension :section, :country metric :pageviews metric :reach, :user_id, :type => :unique metric :clicks, :click?, :type => :predicate end counters = conf.build! måndag 19 mars 12
  31. SNEAK SOME RUBY INTO THAT ENTERPRISE APPLICATION måndag 19 mars

    12
  32. STANDING ON THE SHOULDERS OF GIANTS WITH JRUBY måndag 19

    mars 12
  33. LET’S STACK SOME ABSTRACTIONS ON TOP OF THEM THERE ABSTRACTIONS

    måndag 19 mars 12
  34. Our stack: RabbitMQ We use the Java driver, with a

    JRuby interface we call HotBunnies github.com/ruby-amqp/hot_bunnies måndag 19 mars 12
  35. Our stack: RabbitMQ require 'hot_bunnies' connection = HotBunnies.connect(:host => 'localhost')

    channel = connection.create_channel queue = channel.queue('test_queue') queue.bind('test_exch', :routing_key => 'hi') subscription = queue.subscribe(:ack => true, :blocking => false) do |headers, msg| # do awesome stuff end måndag 19 mars 12
  36. Our stack: MongoDB Go listen to David’s talk tomorrow We

    use the Ruby driver, because we wouldn’t get anything done otherwise måndag 19 mars 12
  37. Our stack: MongoDB BasicDBObject doc = new BasicDBObject(); doc.put("name", "MongoDB");

    doc.put("type", "database"); doc.put("count", 1); BasicDBObject info = new BasicDBObject(); info.put("x", 203); info.put("y", 102); doc.put("info", info); coll.insert(doc); vs. coll.insert( 'name' => 'MongoDB', 'type' => 'database', 'count' => 1, 'info' => {'x' => 203, 'y' => 102} ) måndag 19 mars 12
  38. Our stack: Cassandra We use a JRuby wrapper on top

    of Pelops github.com/iconara/eurydice måndag 19 mars 12
  39. Our stack: Cassandra Mutator mutator = Pelops.createMutator(pool); Column nameColumn =

    mutator.newColumn("name", "Dan"); Column ageColumn = mutator.newColumn("age", Bytes.fromInt(33)); List<Column> columns = mutator.newColumnList(nameColumn, ageColumn); mutator.writeColumns(columnFamily, rowKey, columns); mutator.execute(ConsistencyLevel.ONE); vs. columns = {'name' => 'Dan', 'age' => 33} column_family.update(row_key, columns, :consistency_level => :one) måndag 19 mars 12
  40. Our stack: Akka Scala is nice, but we’ve got better

    things to do than to wait for code to compile Akka is awesome, so we created Mikka github.com/iconara/mikka måndag 19 mars 12
  41. Our stack: Akka class Ping < Mikka::Actor def pre_start @pong

    = context.actor_of(Pong) @pong << :ping end def receive(message) context.reply(:ping) end end class Pong < Mikka::Actor def receive(message) context.reply(:pong) end end ping = Mikka.actor_of(Ping).start måndag 19 mars 12
  42. Our stack: numbers We process hundreds of millions of messages

    per day, using less than 20K lines of JRuby måndag 19 mars 12
  43. twitter.com/iconara architecturalatrocities.com burtcorp.com måndag 19 mars 12