Standing on the shoulders of giants with JRuby

43
STANDING ON THE SHOULDERS OF GIANTS WITH JRUBY måndag 19 mars 12
  • date post

    17-Oct-2014
  • Category

    Technology

  • view

    3.141
  • download

    0

description

Presentation held at Software Passion Summit 2012

Transcript of Standing on the shoulders of giants with JRuby

Page 1: Standing on the shoulders of giants with JRuby

STANDING ONTHE SHOULDERS

OF GIANTSWITH JRUBY

måndag 19 mars 12

Page 2: Standing on the shoulders of giants with JRuby

Theo@iconara

måndag 19 mars 12

Page 3: Standing on the shoulders of giants with JRuby

Chief Architect at

måndag 19 mars 12

Page 4: Standing on the shoulders of giants with JRuby

måndag 19 mars 12

Page 5: Standing on the shoulders of giants with JRuby

ruby

måndag 19 mars 12

Page 6: Standing on the shoulders of giants with JRuby

TL;DRMost of you are Java developersWriting Java is tediousThere’s truckloads of great Java librariesThe JVM is awesomeRuby is awesome∴ JRuby FTW

måndag 19 mars 12

Page 7: Standing on the shoulders of giants with JRuby

I’M NOT HERE TO MAKE FUN OF JAVA

just

måndag 19 mars 12

Page 8: Standing on the shoulders of giants with JRuby

JRuby vs. vanilla RubyReal threadsA working GCEvery Java, Scala and Ruby library ever madeAll the JVM awesomeness, JIT, the lot

måndag 19 mars 12

Page 9: Standing on the shoulders of giants with JRuby

JRuby vs. JavaIt doesn’t make you want to stab yourself

måndag 19 mars 12

Page 10: Standing on the shoulders of giants with JRuby

måndag 19 mars 12

Page 11: Standing on the shoulders of giants with JRuby

JRUBY ♥ JAVAA WHIRLWIND TOUR

måndag 19 mars 12

Page 12: Standing on the shoulders of giants with JRuby

JRuby ♥ Javastuff = TreeMap.newstuff['windmill'] = 'rocket'stuff['pirate'] = 'bees'stuff.each do |something| # redactedend

måndag 19 mars 12

Page 13: Standing on the shoulders of giants with JRuby

JRuby ♥ Javarequire '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

Page 14: Standing on the shoulders of giants with JRuby

JRuby ♥ Javarequire 'java'require 'rabbitmq-client.jar'

import 'com.rabbitmq.client.ConnectionFactory'

factory = ConnectionFactory.newfactory.uri = 'amqp://localhost:5672/'connection = factory.new_connection

måndag 19 mars 12

Page 15: Standing on the shoulders of giants with JRuby

JRuby ♥ Javaclass Worker < Thread def run puts 'Hard work, no play' endend

# or

class Worker include Runnable def run puts 'Hard work, no play' endend

måndag 19 mars 12

Page 16: Standing on the shoulders of giants with JRuby

JRuby ♥ Javapool = 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 endend

pool.shutdownpool.await_termination(3, TimeUnit::DAYS)

memes.each { |m| puts(m) }

måndag 19 mars 12

Page 17: Standing on the shoulders of giants with JRuby

JRUBY FOR REPRESSED JAVA

DEVELOPERS

måndag 19 mars 12

Page 18: Standing on the shoulders of giants with JRuby

Made up fact84% of Java devs don’t write tests because it’s way too much extra code to type.

måndag 19 mars 12

Page 19: Standing on the shoulders of giants with JRuby

Testingpublic 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

Page 20: Standing on the shoulders of giants with JRuby

Testingclass TestPerson < Test::Unit::TestCase def setup @person = Person.new('James', 'Gosling') end

def test_full_name assert_equal('James Gosling', @person.full_name) endend

# this is TestUnit, it’s part of the stdlib

måndag 19 mars 12

Page 21: Standing on the shoulders of giants with JRuby

Testingdescribe 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 endend

# this is RSpec, read more at rspec.info

måndag 19 mars 12

Page 22: Standing on the shoulders of giants with JRuby

Made up factAnt was designed by the same people who came up with the QWERTY layout.

måndag 19 mars 12

Page 23: Standing on the shoulders of giants with JRuby

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 --> <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/> </target> <target name="clean" description="clean up"> <!-- Delete the ${build} and ${dist} directory trees --> <delete dir="${build}"/>

måndag 19 mars 12

Page 24: Standing on the shoulders of giants with JRuby

Automationrequire 'ant'

src_dir = 'src'build_dir = 'build'dist_dir = 'dist'timestamp = Time.now

task :init do mkdir_p build_dirend

task :compile => :init do ant.javac :srcdir => src_dir, :destdir => build_dirend

task :dist => :compile do mkdir_p "#{dist_dir}/lib" ant.jar :jarfile => "#{dist_dir}/lib/MyProject-#{timestamp}.jar", :basedir => build_dirend

task :clean do rm_rf build_dir rm_rf dist_direndmåndag 19 mars 12

Page 25: Standing on the shoulders of giants with JRuby

Made up factThe average number of lines in a Java web application is somewhere around 100 000

måndag 19 mars 12

Page 26: Standing on the shoulders of giants with JRuby

Don’t make it so hardget '/' do erb :indexend

post '/register' do stuff.save(params[:name], params[:email], params[:shoe_size]) redirect '/thanks'end

get '/thanks' do @name = params[:name] erb :thanksend

# this is Sinatra, read more at sinatrarb.com

måndag 19 mars 12

Page 27: Standing on the shoulders of giants with JRuby

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

Page 28: Standing on the shoulders of giants with JRuby

Make a console$ hbase shell

HBase Shell; enter 'help<RETURN>' for list of supported commands.Type "exit<RETURN>" to leave the HBase ShellVersion 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 secondshbase(main):002:0> put 'test', 'row1', 'cf:a', 'value1'0 row(s) in 0.0560 secondshbase(main):003:0> put 'test', 'row2', 'cf:b', 'value2'0 row(s) in 0.0370 seconds

måndag 19 mars 12

Page 29: Standing on the shoulders of giants with JRuby

Monitoringrequire 'jmx'

client = JMX.connect(:port => 7199)

storage_service = client['org.apache.cassandra.db:type=StorageService']storage_service.keyspaces.each do |keyspace| puts keyspaceend

memory_mbean = client['java.lang:type=Memory']puts memory_mbean.heap_memory_usage.used

memory_mbean.gc

måndag 19 mars 12

Page 30: Standing on the shoulders of giants with JRuby

Configurationconf = 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 => :predicateend

counters = conf.build!

måndag 19 mars 12

Page 31: Standing on the shoulders of giants with JRuby

SNEAK SOME RUBY INTO THAT ENTERPRISE APPLICATION

måndag 19 mars 12

Page 32: Standing on the shoulders of giants with JRuby

STANDING ONTHE SHOULDERS

OF GIANTSWITH JRUBY

måndag 19 mars 12

Page 33: Standing on the shoulders of giants with JRuby

LET’S STACK SOME ABSTRACTIONS ON

TOP OF THEM THERE ABSTRACTIONS

måndag 19 mars 12

Page 34: Standing on the shoulders of giants with JRuby

Our stack: RabbitMQWe use the Java driver, with a JRuby interface we call HotBunniesgithub.com/ruby-amqp/hot_bunnies

måndag 19 mars 12

Page 35: Standing on the shoulders of giants with JRuby

Our stack: RabbitMQrequire 'hot_bunnies'

connection = HotBunnies.connect(:host => 'localhost')channel = connection.create_channelqueue = channel.queue('test_queue')queue.bind('test_exch', :routing_key => 'hi')

subscription = queue.subscribe(:ack => true, :blocking => false) do |headers, msg| # do awesome stuffend

måndag 19 mars 12

Page 36: Standing on the shoulders of giants with JRuby

Our stack: MongoDBGo listen to David’s talk tomorrowWe use the Ruby driver, because we wouldn’t get anything done otherwise

måndag 19 mars 12

Page 37: Standing on the shoulders of giants with JRuby

Our stack: MongoDBBasicDBObject 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

Page 38: Standing on the shoulders of giants with JRuby

Our stack: CassandraWe use a JRuby wrapper on top of Pelopsgithub.com/iconara/eurydice

måndag 19 mars 12

Page 39: Standing on the shoulders of giants with JRuby

Our stack: CassandraMutator 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

Page 40: Standing on the shoulders of giants with JRuby

Our stack: AkkaScala is nice, but we’ve got better things to do than to wait for code to compileAkka is awesome, so we created Mikkagithub.com/iconara/mikka

måndag 19 mars 12

Page 41: Standing on the shoulders of giants with JRuby

Our stack: Akkaclass Ping < Mikka::Actor def pre_start @pong = context.actor_of(Pong) @pong << :ping end

def receive(message) context.reply(:ping) endend

class Pong < Mikka::Actor def receive(message) context.reply(:pong) endend

ping = Mikka.actor_of(Ping).start

måndag 19 mars 12

Page 42: Standing on the shoulders of giants with JRuby

Our stack: numbersWe process hundreds of millions of messages per day, using less than 20K lines of JRuby

måndag 19 mars 12

Page 43: Standing on the shoulders of giants with JRuby

twitter.com/iconaraarchitecturalatrocities.com

burtcorp.com

måndag 19 mars 12