Below you will find pages that utilize the taxonomy term “JRuby”
managing multiple ruby versions
Today I read a nice post - in Portuguese - by Fábio Akita on how to manage multiple ruby versions on your machine. I've tried it once with some tool I can't even remember the name but failed miserably.
But this time things look very different. The tool here is the rvm - short for Ruby Version manager - and it works just great.
Let's cut to the chase and imagine that you, like me, want to run/develop/test your code on both ruby 1.8.7 and ruby 1.9.1. These steps would get you up and running in a few minutes:
Install rvm:
$ gem sources -a http://gemcutter.org/
$ gem install rvm
$ rvm-install
$ echo "if [[ ! -z $HOME/.rvm ]] ; then source $HOME/.rvm ; fi" >> ~/.bash_profile
$ source ~/.rvm/scripts/rvm
Install the ruby interpreters you want to use:
$ rvm install ruby-1.8.7-p160
$ rvm install ruby-1.9.1
Now it's important to notice that at this point you have separate gem installations for each of the interpreters you've installed in the previous step. That said, just go ahead and switch between your interpreters and use your command line scripts - ruby, gem, etc... - as usual.
Switching between interpreters:
$ rvm ruby-1.8.7-p160 #switch to the specified version
$ ruby -v
ruby 1.8.7 (2009-04-08 patchlevel 160) [i686-darwin9.8.0]
$ gem install rails #note I'm not using sudo since the new gem paths point to the user's home directory
$ rvm ruby-1.9.1 #switch to the specified version
$ ruby -v
ruby 1.9.1p376 (2009-12-07 revision 26041) [i386-darwin9.8.0]
$ gem install rails #note I'm not using sudo since the new gem paths point to the user's home directory
And that's it, just go on and install rails, merb, sinatra or whatever rocks your boat!
rvm will work with MRI/YARV, JRuby, Ruby EE and Rubinius. Enjoy and don't forget to check rvm's website for the complete documentation! :)
refactoring for readability
Yesterday I've done something I should do more often: Revisit some code written a while ago for our current project and make it better.
Let's face it. We all write crappy code the 1st time. The difference is in what we do about it afterwards.
We might decide it's good enough and keep moving, or we could (and should!) stop and refactor it!
The code I revisited worked as a refactoring exercise and it's initial version is shown below:
class Jphoto
...
#a few other methods ...
def post_photo(file_data, hotel_id, send_rss, options = {})
file_name = "tmp/#{Time.now.to_i}_#{rand(1000000).to_s(36)}"
File.open(file_name, "wb") do |f|
f.puts(file_data)
end
params = [Curl::PostField.file('photo',file_name),
Curl::PostField.content('hotel', hotel_id),
Curl::PostField.content('source','PhotoUploadTest')]
extract_extra_params!(params, options)
c = Curl::Easy.new("#{service_uri_base}/photoupld")
c.multipart_form_post = true
c.http_post(*params)
if c.response_code != 200
error_msg = "File upload failed with code: #{c.response_code}"
Rails.logger.info error_msg
raise error_msg
end
File.delete(file_name)
hotel = Hotel.find_by_id(hotel_id)
hotel.cache.destroy_all
send_upload_rss(hotel, original_upload_url(c.body_str) , options) if send_rss
end
private
def send_upload_rss(hotel, photo_url, options)
...
end
def manage_images_link(hotel_id)
...
end
def extract_extra_params!(params, options)
params << Curl::PostField.content('status', options[:status]) if options[:status]
params << Curl::PostField.content('upload_source', options[:upload_source]) if options[:upload_source]
params << Curl::PostField.content('uploader_ip', options[:uploader_ip]) if options[:uploader_ip]
params << Curl::PostField.content('uploader_email', options[:uploader_email]) if options[:uploader_email]
end
end
Look at the post_photo method. It has problems in so many levels that it’s hard to start.
Methods should do “one thing” and that method obviously does much more than that, mixing different levels of abstraction.
But let’s start with the easy parts first, keeping in mind that I was aiming for readability.
Lines 7 to 10 seem to be there just to make the reader’s life harder. It’s creating a temporary file through some custom logic instead of using the tools provided by the language. Unnecessary and only pollutes our eyes. My first measure was to use ruby’s TempFile class for this. Better, but we still have a long way.
Right at line 12 it creates some sort of default parameters list, after which it extracts some extra options. I don’t know what that method does but it’s clearly using output arguments, which we should avoid at all costs, as they lead to confusion. This is a big smell as well, and another refactoring step added to my list.
On line 21 starts the code that handles what to do when we get a response_code other than 200 from our request. Apart from the fact that this code doesn’t feel right here, we just happen to know that in HTTP, 200 means success, but that might not be clear to someone looking at the code for the 1st time.
Then the code goes on to delete the temp file, clear the hotel’s cache and send the rss if the rss’ flag is true.
Let there be refactoring….
Geez, how many lines have I used to explain what the code does? Since I don’t wanna bore you to death, here is my refactored version of this method, trying to avoid as much as I can the problems I highlighted previously:
rails summit 2009 im speaking
I'll be speaking at this year's Rails Summit Latin America in Sao Paulo, Brazil. It will be a good opportunity to meet some amazing people and visit friends back home! :)
Overall I'll be spending 12 days in Brazil, with 2 of them dedicated to the conference. The other 10 I'll be in Rio de Janeiro visiting my family and friends. I strongly advise you to spend some time in Rio too, if at all possible. It's an amazing city and you can contact me if you have any questions.
Back to the conference, my session is called JRuby in the enterprise world: Using Rails with legacy code, and will be given in the form of a tutorial. I will walk you through some problems we had while making this kind of integration at my company, focusing mostly on dependency management.
At the end I hope you'll have a good understanding of what JRuby is capable of in a legacy environment.
If you're planning to attend and would like to hear anything specific about JRuby, please let me know, I can try and squeeze in.
C u there!
jvm language preferences poll results
- Overall results
First off, I'd like to thank everyone who voted on this poll.
With a total of 236 votes, here is the summary of the first two questions:
- Are you currently working with or researching about language alternatives for the JVM? - e.g. JRuby, Scala, Groovy
{% img /assets/images/scala_improvements.png %}
Tooling. The majority of comment urge for better tooling and IDE support. That simple.
- Others
People who chose others mentioned Clojure, Fan and Jython, with a clear advantage for Clojure.
- Disclaimer
This poll has no scientific foundations whatsoever and its sole purpose is to summarize the feelings and personal choices of the people who answered it. If you would like the original spreadsheet with the answers, you can find it here and do your own analyzis.
jruby on rails and legacy java apps managing dependencies
The motivation for this post came from a couple of messages I've seen on the jruby's google group and because I think it's pretty cool to share how we tackled this problem.
- A little bit of context
We, as a vast amount of people out there, have legacy Java code. A lot. In our case this legacy is pretty much crucial to our business. We can't just trash it and start from scratch. Bad idea.
On the other hand we do have new features to be built on top of it. But we wanted an easier way to develop this new stuff and decided for a JRuby on Rails solution, using it as a front-end to our existing services.
- What we decided to do
Our final rails project would make use of a specially created jar file containing our Java application. This Jar would also contain a public interface of the services we'd have to interact with from rails.
As any Java application, ours depend on a number of external jar files that correspond to the various framewoks we usually have in place. e.g.: Hibernate, Spring, apache-commons ...
Which means we need to make our app's jar and all it's dependencies available in the JRuby classpath in order to use it.
Given we're using warbler to package our application as a war file, we just need to place all jars needed into our rails app's lib folder. Warbler then takes care of copying any jar files located in there into the war.
- The problem
So we needed a smart way to include all these dependencies into the project, and copy/paste isn't an option.
In the Java world we use Maven to manage our projects dependencies - and you should too. Because of that our approach involved turning our rails application into a Maven aware project.
Basically we needed a pom file that would declaratively list our java project as a dependency. From there on, Maven knows what the dependencies are and downloads them to your local repository.
Which leaves us with one more task. We need to put all these dependencies into our lib folder after maven has downloaded them.
Below you'll find the pom.xml file that we use to achieve this with inline comments explaining each bit:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<!-- notice how we specify the packaging to be a war,
that way, maven knows where to copy the jar files -->
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<artifactId>railsApp</artifactId>
<name>railsApp</name>
<dependencies>
<dependency>
<groupId>com.company</groupId>
<artifactId>java-legacy-app</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>railsApp</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<!-- This tasks only creates a basic structure expected by maven,
so it can do its work -->
<id>create-mock-web-descriptor</id>
<phase>compile</phase>
<configuration>
<executable>/bin/sh</executable>
<workingDirectory>.</workingDirectory>
<arguments>
<argument>-c</argument>
<argument>
mkdir -p src/main/webapp/WEB-INF
touch src/main/webapp/WEB-INF/web.xml
</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
<execution>
<!-- Now in the package phase we copy the jar files
that maven put into the fake web app to our rails' lib folder -->
<id>copy-needed-jars-into-lib</id>
<phase>package</phase>
<configuration>
<executable>/bin/sh</executable>
<workingDirectory>.</workingDirectory>
<arguments>
<argument>-c</argument>
<argument>
rm -f lib/*.jar
cp target/railsApp/WEB-INF/lib/*.jar lib
rm -rf target/railsApp*
rm -rf src
</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
<execution>
<!-- Here we optionally create the final war file containing our rails app using warbler,
doing a small cleanup of the files and folders maven created -->
<id>create-final-war</id>
<phase>package</phase>
<configuration>
<executable>/bin/sh</executable>
<workingDirectory>.</workingDirectory>
<arguments>
<argument>-c</argument>
<argument>
rm -rf *.war tmp/war
jruby -S warble && \
mv *.war target/railsApp.war
</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Now from the command line we can just run mvn package and we’re good to go.
Maven will start to package the application as a war file. Since it’s not a Java application we create the empty web.xml file in the compile phase, to fool maven.
After it has copied all the dependencies into WEB-INF/lib the next packaging goals will make sure we copy them to our rails’ lib folder, also creating the final war file, ready for deployment.
Note that once done, you can use a simple code snippet similar to this one as an initializer and load all dependencies:
Dir.entries("#{RAILS_ROOT}/lib").sort.each do |entry|
if entry =~ /.jar$/
require entry
end
end
Then we can just use script/console, script/server and so on, as we normally would.
Sorry for the long post, I tried to pack in as much as I could and I certainly hope it’s useful to someone. Any doubts, comments and etc… just drop me a line. :)
google io thoughtworks on gae
I've just watched a video from Google IO where Martin Fowler and Rebecca Parsons went through some of the aspects that involves the development of an application for the cloud - focusing on the JVM.
In terms of the Google App Engine, you don't have access to a relational database, thing I found out when I first tried it. Instead you get a Big Table.
Martin put out a good analogy and you can just think of it as a nested hash map. It's certainly a shift on how we think these days, but layers of abstraction like google's DataStore and the Java Persistence API will help in the transition.
Another interesting bit about the presentation was on how concurrency works on GAE.
Essentially, in an standard Java application you have a single memory space where you have at least one running thread. You can create threads on the fly, which will share the same memory space, thus making it easy to share data.
On the app engine, things work differently. What you have are separate memory spaces with a single thread on each one. Any attempt to create a new thread will result in an exception. The solution for sharing information in this case? Use the nested hash map (big table).
Now, whereas you might not be worried about this since your application doesn't span any threads, as well pointed by Martin Fowler, it's the code you don't see that you need to be careful with. Any Java application uses a number of 3rd party libraries that might span out threads of their own, which will result in your application blowing up.
That rang a bell. Again, back when I was trying the app engine, one of the configuration bits shared by Ola Bini looked like this:
config.webxml.jruby.min.runtimes = 1
config.webxml.jruby.max.runtimes = 1
config.webxml.jruby.init.serial = true
I think the properties are pretty much self-explanatory but I didn't quite understand the reason for setting it back then.
If you happen to have bigger values for the number of runtimes you want, you need to set the serial property to true, otherwise JRuby will span several threads to create the runtimes.
This is a really good example of things that might fail whether you're migrating or developing a new app to deploy on the App Engine. Luckily for us, JRuby has a smart and neat way to handle this - the configuration I've just shown, but most of the libraries out there that might rely on threads are not prepared.
Martin and Rebecca's opinion on this is that new releases of these same libraries will start to take it into account, since a bigger adoption of the Cloud seem to be on the way.
Make sure you watch the video. I certainly left a lot of interesting stuff out.
helping the jruby effort debugging the source
Wanna help improve JRuby? Make sure you read this post by Charles Nutter first. There he explains how to run Ruby specs with JRuby.
Start with fixing Ruby specs is a great way to get acquainted with the code. And it’s also a important task in order to make sure JRuby is the most complete and compatible ruby implementation out there.
But before you get your hands dirty, it will be a lot easier if you can actually debug JRuby’s source while fixing any specs - or bugs/features for that matter.
railswaycon jruby internals by ola bini
As always I expected a good talk from Ola and once more he delivered it. But this one was different. It might have been even boring to some ruby developers since we saw a fair amount of java code in this presentation. Ola gave us a tour through the main classes that make JRuby possible with a single purpose: so we can check out the code and hack ourselves. You can download his slides here.
If you've been following both JRuby and Ola Bini for the past year or so, you've noticed the trend and evolution of this alternative - and so far the most complete one - implementation of the ruby language. Specially at conferences.
Last year at QCon London, Ola was also talking about JRuby. At Euruko '08, in Prague, Charles Nutter also talked about it. RailsConf in Berlin also had its share. What all these talks had in common is that they talked about JRuby from a user/developer point of view. They were selling the solution. Convincing people to use it and presenting successful use cases.
And as the trend goes on, JRuby is now faced as a true alternative - one that we, btw, believe here at the company as we're actively using it - and it seems that now the call is for help. Help to make JRuby an even more complete and overall better ruby implementation. Charles' call for help was a great step. As he states, it's a good way to get your feet wet. I answered the call and am hacking JRuby myself, having already submitted a couple of patches. Perhaps this was the reason for which I enjoyed the talk the most. I was already familiar with some of the structure and classes in JRuby.
There were 2 more talks about JRuby: The Pleasure and Pain of Migrating to jRuby, by Steven Bristol and Integrating Enterprise Java with JRuby and Rails, Michael Johann. Unfortunately only the first one was a real case experience, where Steven walked through the problems he faced integrating JRuby with an existing java project. Interesting insights.
Michael Johann basically presented a short tutorial on how to integrate rails with EJB3 which, albeit interesting, failed to address issues faced on real life projects, like dependency management. Issues which we have already addressed in a very cool way here and I plan to share it soon. Still deciding how though...
rcov jruby and rcov_plugin
The rcov_plugin project is a rails plugin for rcov that adds some useful rake tasks to your application. And since I'm currently working in a JRuby project it made sense to use this plugin.
The thing is, among other stuff, an rcov report from a JRuby project includes some files that shouldn't be there at all, plus you also need to change the way you call rcov as such. Thus, I thought I'd contribute these changes to the plugin and my pull request was approved this morning - just install the latest version and you should be good to go.
It was useful for us here, hope it might be useful for you too.
Enjoy :)
jruby on rails and google app engine
As many of you know the new language supported at GAE now is Java, as officially announced on their blog. As a Ruby/Rails developer you might not be interested on it but here is a reason you should be: JRuby.
It was only a matter of time until we saw some people deploying JRuby on Rails apps on GAE, like Ola Bini's mini blog app. Guess that was the first one really, as he was beta testing the service in secret. Google App Engine imposes a few catches to any java application deployed there and any JRuby app wouldn't be different. For instance, your Java API access is limited to these classes - called JRE Class whitelist.
As you can see on his blog, you don't need active record and in fact shouldn't even be loading that on your app.
I felt compelled to try it and the timing was perfect. I am currently developing a JRuby on Rails app at the company I work for and it was a perfect fit, since we are not using ActiveRecord. The reason is that we get the data we need from other sources, such as web services and even text files.
Ola Bini's tips were crucial here. He provides a small script you can use to prepare the jars you're sending to your app. Another important piece was the Google App Engine SDK for Java. It ships with a server that emulates GAE's behaviour locally so you're less likely to have problems once you deploy it.
I did have a problem though with the number of files uploaded to my appspot. It's currently limited to 1000 - a thousand - and a Rails app can easily exceed this limit. So before deploying, remove anything that is not crucial: activerecord - you should've done it already - , all tests directories - including the ones inside gems your app needs in order to work, fixtures and etc.
After that it was rewarding seeing a custom JRuby On Rails application working perfectly on GAE. And as much as I'd like to, I can't really share the URL since it's a private app but I encourage people to try it. I believe GAE will ultimately help the community improve JRuby even more.
And as a last tip, this time thanks to Fabio Akita, is this snippet. You should redirect your log so you can debug your app form GAE's dashboard.
Have fun!
jruby db2 xquery bug
Update: Follow up link to this issue on JRuby's Jira, here
As I told in my last post, it was time to give JRuby a serious try. So I took one of our rails projects at work and decided to migrate it to JRuby and see what happens.
We heavily use the XML capabilities of DB2 and this was a huge problem. Every query would work just fine through the activerecord-jdbc-adapter - part of the JRuby Extras . But every Xquery would gracefully fail!
After some debugging I got stuck and decided to get JRuby and activerecord-jdbc-adapter's source to see what was happening.
As I could see, it has a bug -in my opinion - at the java part of the code. The jdbc-adapter is a bridge to allow Active Record to talk with databases through native JDBC drivers, so it's normal that we do have a java part here. At this point, what the code does is to inspect the sql statement sent from ruby and decide if it's a select, update or insert.
I fixed the problem and submitted a patch to rubyforge. I'm not sure if it's the best solution or not, but now I got the xQueries working just fine.
I'd love to hear from people with similar environments whether this patch works for you or not. I'm sure I didn't try every possibility.
If you wanna try it, just drop me a message (e-mail in the About page) and I can send the pre-compiled jar file - for activerecord-jdbc-0.8
You can also just check out the code and compile yourself. ;)
qcon 2008 slides available
Most of last QCon's presentations are available for download here.
Highlights to Ola Bini's on JRuby(pdf) and Randy Shoup's on eBay's architectural principles(pdf).
And while we're talking about JRuby, it's impressive how it's becoming a recurrent and big subject. Fast. It had its own small space at big event like QCon and in the last Euruko in Prague, we had a presentation by the JRuby Core Developers Charles Nutter and Thomas Enebo.
Big companies are sponsoring JRuby's development indirectly or directly, like Sun. And other big companies are endorsing its production ready state, like Oracle, which has a publicly available website developed with JRuby On Rails.
It's past the time to give it a serious try...