How to Call Java API from Ruby 1.8 or 1.9

How to call Java API from Ruby 1.8 or 1.9

As commented above, you can not do this directly from the Ruby runtime, calling Java from Ruby requires you to be either on JRuby or call Java indirectly using the C/C++ JVM API that allows you to call Java code from C.

The first option is possibly using Ruby Java Bridge that does most of the heavy lifting for you (it functions as a Ruby-to-C-to-Java wrapper).

If RJB doesn't work for you, you can also build your wrapper directly by using the JVM API in C ( example here ) and then you could call it from Ruby using FFI.

But unless you really need to use the C-Ruby (MRI) I would greatly recommend you to avoid any of the approaches above and just use JRuby, as delving into native code will lead to possible segfaults, memory management issues and all options above force you to run in a single thread, while you could build a multi-threaded solution by using JRuby.

How do I use a Java library (like JDBC) in C Ruby?

Cribbing an answer from this question:

You could build a wrapper using the C JVM API and then call it from Ruby using FFI, or you could use a project called Ruby Java Bridge (RJB).

How to make JRuby 1.6 default to Ruby 1.9?

Use the JRUBY_OPTS environment variable. JRUBY_OPTS holds a list of arguments that are added to any arguments specified on the command line.

For example (on Linux):


$ jruby -v
jruby 1.6.0.RC1 (ruby 1.8.7 patchlevel 330) (2011-01-10 769f847) (Java HotSp...
$ export JRUBY_OPTS=--1.9
$ jruby -v
jruby 1.6.0.RC1 (ruby 1.9.2 trunk 136) (2011-01-10 769f847) (Java HotSpot(TM...
$ export JRUBY_OPTS=--1.8
$ jruby -v
jruby 1.6.0.RC1 (ruby 1.8.7 patchlevel 330) (2011-01-10 769f847) (Java HotSpo...

JRuby with Ruby 1.9

A detailed overview of what is done and what is missing can be found on their wiki. From that page:

These are entire areas that need to be worked on.

  • Encoding::Converter
  • Yielder/Generator
  • key Marshal changes
  • cli options
  • some RubyBignum changes
  • possible other changes in Numerics
  • changes in Dir/IO/File (some obvious things are done, like enumeratorize)
  • some changes in Math
  • encoding information in exception messages (now passed via java String)
  • BigDecimal changes ?

In general, though, I think you'll be fine if you use JRuby for Ruby 1.9 code. Any errors that you may have will be few and far between, and easily fixable (for the most part). I recommend you try your code with the latest JRuby, and if it doesn't work, then you know not to use it yet.

Ruby 1.8.7 versus Ruby 1.9+ performance

These could help you

http://nerds.airbnb.com/upgrading-from-ree-187-to-ruby-193

http://blog.pothoven.net/2012/10/ruby-187-vs-193-performance.html

http://pulse.sportngin.com/news_article/show/156863?referrer_id=543230

note that ruby 2 has even better performance

Ruby and JRuby difference in method chain

The difference you are seeing is not an incompatibility between Ruby and JRuby per se. JRuby 1.7.x defaults to compatibility with Ruby 1.9.3, and so what you are actually seeing is the difference in behaviour of the Array#to_s method between Ruby 1.8.7 and Ruby 1.9.3.

You can turn on JRuby's 1.8-compatibility mode by passing the switch '--1.8' to the jruby command or by setting the environment variable JRUBY_OPTS like this:

export JRUBY_OPTS='--1.8'.

For example, this is JRuby 1.7.2's default 1.9-compatibility mode:

$ JRUBY_OPTS='' irb
> ([] << 9 << 8 << 0 << 2).to_s
=> "[9, 8, 0, 2]"

And here's the result with 1.8-compatibility turned on:

$ JRUBY_OPTS='--1.8' irb
> ([] << 9 << 8 << 0 << 2).to_s
=> "9802"

How to use Stanford CoreNLP java library with Ruby for sentiment analysis?

As suggested in the comments by @Qualtagh, I decided to use JRuby.

I first attempted to use Java to use MongoDB as the interface (read directly from MongoDB, analyze with Java / CoreNLP and write back to MongoDB), but the MongoDB Java Driver was more complex to use than the Mongoid ORM I use with Ruby, so this is why I felt JRuby was more appropriate.

Doing a REST service for Java would have required me first to learn how to do a REST service in Java, which might have been easy, or then not. I didn't want to spend time figuring that out.

So the code I needed to do to run my code was:

  def analyze_tweet_with_corenlp_jruby
require 'java'
require 'vendor/CoreNLPTest2.jar' # I made this Java JAR with IntelliJ IDEA that includes both CoreNLP and my initialization class

analyzer = com.me.Analyzer.new # this is the Java class I made for running the CoreNLP analysis, it initializes the CoreNLP with the correct annotations etc.
result = analyzer.analyzeTweet(self.text) # self.text is where the text-to-be-analyzed resides

self.corenlp_sentiment = result # adds the result into this field in the MongoDB model
self.save!
return "#{result}: #{self.text}" # for debugging purposes
end

how to dynamically call a method while respecting privacy

As I know - you need method public_send:

----------------------------------------------------- Object#public_send
obj.public_send(symbol [, args...]) => obj

From Ruby 1.9.1
------------------------------------------------------------------------
Invokes the method identified by _symbol_, passing it any arguments
specified. Unlike send, public_send calls public methods only.

1.public_send(:puts, "hello") # causes NoMethodError

Adding method to class in Ruby

When you include a module, the methods contained in it are loaded into the "instance" level of methods.

If you want to include methods from a module into the Class scope, you have to extend the module.

Or if you need both, but you want to package it as a single "include", you can extend the "included" method of the module you're extending and do a bit of magic with it by extending and including 2 modules from there.

module Observable

def self.included(other)
other.send(:include, InstanceMethods)
other.send(:extend, ClassMethods)
end

module InstanceMethods
def some_helper
puts "called some_helper"
end
def other_helper
puts "called other_helper"
end
end

module ClassMethods
def observe_attribute(name)
# do something useful, maybe in your case define the method
define_method("#{name}=") do |val|
puts "called #{name}= #{val}"
# bla bla
some_helper
other_helper
# end
puts "done"
end
end
end

end

class Foo
include Observable
observe_attribute :foo
end

Now you can call ...

o = Foo.new
o.foo = :bar

And then the result would be ...

called foo= bar
called some_helper
called other_helper
done


Related Topics



Leave a reply



Submit