Standing on the shoulders of giants with JRuby
-
date post
17-Oct-2014 -
Category
Technology
-
view
3.141 -
download
0
description
Transcript of Standing on the shoulders of giants with JRuby
STANDING ONTHE SHOULDERS
OF GIANTSWITH JRUBY
måndag 19 mars 12
Theo@iconara
måndag 19 mars 12
Chief Architect at
måndag 19 mars 12
måndag 19 mars 12
ruby
måndag 19 mars 12
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
I’M NOT HERE TO MAKE FUN OF JAVA
just
måndag 19 mars 12
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
JRuby vs. JavaIt doesn’t make you want to stab yourself
måndag 19 mars 12
måndag 19 mars 12
JRUBY ♥ JAVAA WHIRLWIND TOUR
måndag 19 mars 12
JRuby ♥ Javastuff = TreeMap.newstuff['windmill'] = 'rocket'stuff['pirate'] = 'bees'stuff.each do |something| # redactedend
måndag 19 mars 12
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
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
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
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
JRUBY FOR REPRESSED JAVA
DEVELOPERS
måndag 19 mars 12
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
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
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
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
Made up factAnt was designed by the same people who came up with the QWERTY layout.
måndag 19 mars 12
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
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
Made up factThe average number of lines in a Java web application is somewhere around 100 000
måndag 19 mars 12
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
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
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
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
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
SNEAK SOME RUBY INTO THAT ENTERPRISE APPLICATION
måndag 19 mars 12
STANDING ONTHE SHOULDERS
OF GIANTSWITH JRUBY
måndag 19 mars 12
LET’S STACK SOME ABSTRACTIONS ON
TOP OF THEM THERE ABSTRACTIONS
måndag 19 mars 12
Our stack: RabbitMQWe use the Java driver, with a JRuby interface we call HotBunniesgithub.com/ruby-amqp/hot_bunnies
måndag 19 mars 12
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
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
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
Our stack: CassandraWe use a JRuby wrapper on top of Pelopsgithub.com/iconara/eurydice
måndag 19 mars 12
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
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
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
Our stack: numbersWe process hundreds of millions of messages per day, using less than 20K lines of JRuby
måndag 19 mars 12
twitter.com/iconaraarchitecturalatrocities.com
burtcorp.com
måndag 19 mars 12