Dec
1
Spring, JRuby and Rails
By Taylor
Filed Under Software
I’m the process of porting our application. Our objective is to increase the velocity of our development. Our current framework, Tapestry5, has proven cumbersome and problematic (I dicussed my thoughts on Tapestry5 earlier, feel free to read through for details). In furtherance of velocity, one should always consider the RAD frameworks, mainly RoR and Grails.
Given some of the API’s we need to use we can’t entirely get away from the Java world, but we have a large, highly talented pool of Ruby on Rails developers to draw on. We also have a robust service layer built using packages like Hibernate, Quartz, and Spring Security, as well as domain-specific packages that are more mature in the Java world.
This presents a challenge; the talent pool screams RoR and the service layer constraints scream JVM (Grails). From a purely technical standpoint, Grails seems the obvious choice, however, the ability to leverage an existing, vetted RoR resource pool is too appealing to a small tech company to resist. Further, while I love Grails, it is a bit immature still.
I’m POC’ing a way to have my cake and eat it too (and avoid a data migration). The approach is to hook a RoR web tier onto a Spring managed service layer, using the wonders of JRuby. I want to be clear, I don’t suggest this to anyone looking to build a new application. Chris Nelson, who wrote a plugin used in this, says:
“If you’re a Java programmer new to (J)Ruby and are thinking: “Awesome, I’ll use Spring in all my Rails apps because Spring is awesome!” you need to hold up a second. Spring is awesome — when you are developing Java applications. But in Ruby, dependency injection turns out to be unnecessary a whole lot of the time. This is because the Ruby language allows you to change things in a more straightforward way. And even if there were cases where you needed DI in Ruby there are probably better choices. I see the Spring plugin being useful where you have existing J2EE code wired together with Spring and want to front end it in JRuby on Rails.”
I couldn’t have said it better myself. So, bearing that in mind, on to the technical details.
First, you need to pull down the latest version of Goldspike, a JRuby on Rails integration package. This can be done with the following command in the root of your rails app:
jruby -S script/plugin install svn://rubyforge.org/var/svn/ jruby-extras/trunk/rails-integration/plugins/goldspike
I’m going to assume you already know how to setup your Spring context, if you don’t the Spring docs can help. You’ll need to make sure you compile a jar with dependencies. To accomplish this, add the following inside the build/plugins of your pom.xml:
<plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin>
You need to get the resulting jar into your Rails application’s lib folder.
You’ll need to install warbler:
jruby -S gem install warbler
Run warble and then copy the generated tmp/war/WEB-INF/web.xml into the Rails application’s config folder.
You’ll need to modify the web.xml to add the Spring context listener by adding the two following:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:service-context.xml</param-value> </context-param> <!-- ... --> <listener> <listener-class>org.springframework.web.context. ContextLoaderListener</listener-class> </listener>
I have my spring context, called service-context.xml in my jar and am loading it from there.
Now all we need to do is call a spring service from a Rails controller, and it turns out thanks to Chris Nelson’s work this uses no ugly glue code in the controller like one might expect:
class SpringTestController > ApplicationController include Spring spring_bean :testService def show @value = testService.value end end
In the above, I pull a spring bean id’ed as testService out of the Spring context and from that pull a value and store it in a rails variable. I can then use that as a normal rails variable in .html.erb
At this point you should be good to go, but I ran into problems with getting JRuby on Rails to connect to mysql. Turns out you need to specify the mysql gem in your config/warble.rb to ensure it’s included in the war. I just added this line to it:
config.gems += ["activerecord-jdbcmysql-adapter"]
After that, run warbler using the warble command in your rails package, and the war should be created in the rails application’s root. Move it over to your favorite web container and you should be set.
Comments
4 Responses to “Spring, JRuby and Rails”
Leave a Reply
What the Fu%&*@ are you talking about????
I’m talking about Spring, JRuby and Rails.
It’s technical stuff, Uncle Dan.
This is a great intro spring, jruby and rails.
As a JEE dev with some Ruby experience I wanted to see how I could add more Ruby to my work environment and this is a great start.
Thanks
Glad you found it useful. Please feel free to add you experiences as you progress, I’d love to read them.