Having used Java as my main language lately, it was about time to play with some new languages. As there is a whole stack of languages that runs on the JVM now, it is hard to decide which language to play with – so I ended up playing with them all, or at least the following; JRuby, Jyhton, Groovy, Scala and Clojure.
Although they all run on the JVM, I wanted to find out how easy it actually is to combine them. My method was almost like this:
Install the programming language (thank you macports)
Find and install the correct plugin for Eclipse
Try execute some Java Library / code from the language
Try to execute something written in the language from Java
On some occasions I also tried to execute some of the other languages from the current language I was playing with.
Disclaimer: I just want to share what I have learnt so far. There might be way better ways to do these things.
Groovy
To install Groovy I just did sudo port install groovy
, whatever platform you are on, it shouldn’t be too hard.
I also installed the Groovy Eclipse Plugin and created a new Groovy Project.
Here is the Groovy code I wrote for calling Java
package groovyerlingwl;
import java.util.regex.Pattern
class CallingJava2 {
def pt = Pattern.compile("^foo")
def m = pt.matcher("foo")
}
def callingJava = new CallingJava2()
println "" + callingJava.m.find()
To call some of my Groovy code from Java, I created a simple class:
package groovyerlingwl;
class GroovyPrinter {
def printsomething() {
println "hello from Groovy"
}
}
..and exported it as a .jar file. Interestingly enough, the .jar file now contained a groovyerlingwl/GroovyPrinter.class. To run this from Java, I had to add groovy-1.6.5.jar and asm-2.2.3.jar to the classpath. I found mine in /opt/local/share/java/groovy/lib. And all the code you need is:
import groovyerlingwl.*;
public class CallingGroovy {
public static void main(String[] args) {
GroovyPrinter gp = new GroovyPrinter();
gp.printsomething();
}
}
Scala
Very much like Groovy, Scala integrates simply with Java. After installing Scala, the Scala Eclipse Plugin and created a new Scala Project; I used the following to call Java:
package erlingwlscala;
import java.util.regex.Pattern
object Test {
def main(args: Array[String]) {
val pt = Pattern.compile("^foo")
val m = pt.matcher("foo")
println(m.find)
}
}
And then I made another simple class to call from Java:
package erlingwlscala
class TestPrinter {
def print_something(){
println("Hello, from scala")
}
}
Again, I exported this to a .jar file. This also resulted in the .jar file containing a erlingwlscala/TestPrinter.class.
To run the class from Java, I added scala-library.jar to the classpath and ran the following Java code
import erlingwlscala.TestPrinter;
public class CallScala {
public static void main(String[] args) {
TestPrinter testPrinter = new TestPrinter();
testPrinter.print_something();
}
}
JRuby
Again, I installed JRuby and the matching Eclipse Plugin. I created a new Ruby Project. However, make sure you choose the JRuby interpreter when running the following code:
require 'java'
include_class 'java.util.regex.Pattern'
class CallingJava
pt = Pattern.compile("^foo")
m = pt.matcher("foo")
puts m.find
end
Running JRuby from Java was not as easy as Groovy or Scala. However, using the JSR-223 it seems that you can run almost any scripting language from Java. So using the approach described in the article you can do the following in Java:
import javax.script.*;
public class CallJRuby {
public static void main(String[] args) throws Exception {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("jruby");
try {
engine.eval("puts('Hello from JRuby')");
} catch (ScriptException exception) {
exception.printStackTrace();
}
}
}
NB! Remember to download The JSR engines and include the jruby-engine.jar on the classpath. You also need to include jruby.jar on the classpath.
Clojure
Again, installing the suiting Eclipse Plugin. And creating a new Clojure plugin. I used the example from Clojure.org and borrowed the following code:
(doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))
To call Clojure from Java, I found this article.. First make a simple clojure program
; printer.clj
(ns printer)
(defn print-string [arg]
(println arg))
Add this to your resources folder in your Java project, include clojure.jar and clojure-contrib.jar on the classpath, and run the following code:
package erlingwl;
import clojure.lang.RT;
public class CallingClojure {
public static void main(String[] args) {
try {
RT.loadResourceScript("printer.clj");
RT.var("printer", "print-string").invoke("hello world");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Jython
Once again, I installed Jython and downloaded the respective Eclipse Plugin. To call Java I created a new Jython project and used the following code (got it from wiki.python.org):
from java.util import *
r = Random()
print r.nextInt()
wiki.python.org also describes how you can use JSR-223 to run Jyhton/Python from Java. I tried the following code:
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class CallJython {
public static void main(String[] args) {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("python");
try {
engine.eval("print 'hey from python'");
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
To get this to work, add jython.jar and the jython-engine.jar from The JSR engines to the classpath.
Bonus
I mentioned I tried to combine some of the other languages too.
Clojure calling scala:
(println (doto (new erlingwlscala.TestPrinter) (.print_something)))
To do this, I added my scala application .jar to the classpath (see above where I call Scala from Java), and also I had to add the scala-library.jar.
JRuby calling clojure:
Here I basically followed the same approach approach as when I called Clojure from Java (see above):
require 'clojure.jar'
include Java
import 'clojure.lang.RT'
class CallingClojure
RT.loadResourceScript("resources/printer.clj")
RT.var("printer", "print-string").invoke("hello world")
end
Calling Scala from JRuby:
My worst hack so far, I assume there are more elegant ways to do this:
include Java
SCALA_HOME = '/opt/local/share/scala/lib/'
require SCALA_HOME + 'scala-library.jar'
require "scalaexport1.jar"
include_class 'erlingwlscala.TestPrinter'
class CallingScala
printer = TestPrinter.new
printer.print_something
end