-
Notifications
You must be signed in to change notification settings - Fork 0
JRubyOnRailsWithSpring
These steps will get you from zero to a working JRuby on Rails app that can access Spring configured beans using maven to manage your dependencies.
Basic Steps:
- For Rails 2
- Download jruby somewhere
tar xvfz jruby-bin-1.4.0.tar.gzmv jruby-1.4.0/ /Applications # I keep stuff here, but the location doesn't mattercd /Applicationsln -s jruby-1.4.0/ jruby- Add
/Applications/jruby/binto my path jruby -v # should workjruby -S gem listjruby -S gem install railsjruby -S gem install activerecord-jdbcmysql-adapterjruby -S gem install jruby-openssljruby -S gem install warblercd ~/workspacejruby -S rails app_name- Commit to version control for easy rollbacks:
git init .git commit -a -m 'initial version' # need a baseline in case we must rollback
jruby -S script/generate resource yourApp-
If you don't want ActiveRecord: Add
config.frameworks -= [ :active_record ]toenvironment.rb - create
app/views/benchmarks/index.html.erb - remove
public/index.html - Add
map.root :controller => "benchmarks"toroutes.rb jruby -S script/server- open
http://localhost:4000- your app is running
- For Rails 3
- Recommend you install [RVM|https://rvm.beginrescueend.com/]
rvm install jruby-
gem intall rails(Note that RVM handles the "jruby" stuff for you) rails new myapp -m http://jruby.org/rails3.rb -d mysqlcd myapp- Edit your
Gemfileas follows:source 'http://rubygems.org'gem 'rails', '3.0.9'gem 'activerecord-jdbc-adapter'gem 'activerecord-jdbcmysql-adapter'gem 'jdbc-mysql'gem 'jruby-openssl'gem 'jruby-rack'
bundle install- Edit your
config/database.yml, setting the theadapter:tojdbcmysql - Edit your
config/database.ymlsetting the appropriate database user/passwords -
Create the databases yourself - there is a bug that prevents
rake db:createfrom working. rake db:migraterails server- Visit
localhost:3000and click on "About your Application's Environemnt". If you don't see any errors, you are good to go - Commit to version control for easy rollbacks:
git init .git commit -a -m 'initial version' # need a baseline in case we must rollback
rails generate resource yourApp-
If you don't want ActiveRecord: Add
config.frameworks -= [ :active_record ]toenvironment.rb - create
app/views/benchmarks/index.html.erb - remove
public/index.html - Add
map.root :controller => "benchmarks"toroutes.rb rails server- open
http://localhost:3000- your app is running
- Commit to version control
How to create Java classes in JRuby.
blah = java.util.Date.new
We don't need Maven a whole lot, if at all, for Rails development, however it is handy to use it to manage our dependencies, especially if you have parent poms or other re-usable components already in your organization.
Courtesy of this awesome blog post, we have a pom that will copy all of our needed jar files into the rails app's lib/ directory. Note that you have to run this manually whenever you change your dependencies. Your pom.xml will look something like:
<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>
<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>
<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>
<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>
Then, to update dependencies:
mvn package # downloads jars into target/ dir,
# then copies them to the lib dir
Finally, Rails needs to load all of these when it starts up. Create config/initializers/01_java_jars.rb:
Dir.entries("#{RAILS_ROOT}/lib").sort.each do |entry|
if entry =~ /.jar$/
require entry
end
end
This basically "loads" all the libs you had maven copy into your app's lib directory. You'll need to restart
rails to see this.
One thing that wasn't clear to me with JRuby is what "package roots" are available by default. For example, my company has code with a package rooted at poscore, and ruby code like poscore.model.type.Customer.new just didn't work. It seems that only certain common top-level packages are automatically available without qualifying, so you can certainly do:
c = Customer.new
I opted to add some methods to application_controller.rb, since I'd be needing these a lot. There are other methods of simulating Java's import something.* hanging around, but this worked for my purposes:
# Get the poscore package from Java def self.poscore; Java::poscore; end
One of the coolest things about JRuby and Rails is that you can package up your Rails app as a .war and dump it into a J2EE app server:
jruby -S warble config # this sets up stuff to make a war jruby -S warble # creates blah.war in local dir
Basically, you need to get a list of all the spring configuration files you intend to load. If your XML configuration files are somewhere in the classpath in a directory called config, you can get a list of them as such
# Our config files live in src/main/resources/config
def beans
["configurationContext", "otherContext", "dataContext" ].map { |c|
"classpath:config/#{c}.xml"
}.to_java :string
end
You can then load them as such:
context = org.springframework.context.support.ClassPathXmlApplicationContext.new(beans)
# We have a bean named "someService" configured, so we get it
service = context.getBean("someService")
You should probably put this in an initializer, naming it to ensure it happens after your java jars are loaded. Using the naming scheme from above, the name config/initializers/02_spring.rb would work as such:
SPRING_CONTEXT = org.springframework.context.support. ClassPathXmlApplicationContext.new(SPRING_XML_CONFIG_FILES)
Again, this assumes that our config files are on the classpath in a config subdirectory. Your setup may need to be different.
Now, you can use SPRING_CONTEXT anywhere in your code to access beans. With Ruby's awesome meta-programming, it's not hard to envision some slick method_missing means of getting access to your beans:
class << context
alias old_method_missing method_missing
def method_missing(sym,args)
if args.empty?
getBean(sym.toString)
else
old_method_missing(sym,args)
end
end
end
context.someService # gets our someService bean
That's it! You now have a JRuby on Rails application that can access your existing java-defined Spring beans.