SpringOne Americas

Private Events

Blogs

View all Blogs >>
  • Howard Lewis Ship

    Creator of Tapestry and HiveMind

    It took a lot of ferreting out, but I eventually learned that you can put a <version/> tag in your site.xml, and Maven will put the... more»

  • Brian Pontarelli

    Founder of Inversoft

    Just figured out how to get git tab completion working in zsh on a Mac. Turns out that the completion scripts use a bunch of extra git... more»

  • Stuart Halloway

    CEO of Relevance

    Steve Yegge's most recent post takes more»

  • Mike Levin

    Software Developer specializing in Web2.0 websites

    more»

  • Erik Doernenburg

    Principal Consultant @ Thoughtworks

    If you are somebody who writes code you probably know that moment when you look at some code you didn’t write, or some code you wrote a... more»

  • Kirk Knoernschild

    Software Developer & Mentor

    more»

  • Richard Monson-Haefel

    VP of Developer Relations, Curl Inc.

    more»

  • Alex Miller

    Sr. Engineer with Terracotta Inc.

    Start your engines kids - the JavaOne 2009 more»

  • Brian Goetz

    Author of Java Concurrency in Practice

    I live in an AT&T-free state, so I have not had access to the cult that is iPhone. But recently, in preparation for AT&T moving... more»

  • Matthew Bass

    Software Developer & Entrepreneur

    Can Sphinx and foxy fixtures place nicely together? Due to the way Sphinx indexing works, foxy fixtures will often slow down the indexing... more»

  • Jason Rudolph

    Author of Getting Started with Grails

    I had the more»

  • Ryan Shriver

    Business and Technology Consulting

    more»

  • Neal Ford

    Application Architect at ThoughtWorks, Inc.

    One of the techniques I more»

  • Michael Nygard

    Agile technology leader and dynamicist

    Patrick Muellr has an interesting post about being more»

  • Nathaniel Schutta

    Author, speaker, software engineer focused on user interface design.

    Today we learned something important, the NTSB announced the more»

  • Jeff Brown

    SpringSource Engineering And Professional Services - Groovy and Grails Developer

    Strange enough title.Let's start with a hypothetical conversation between a geeky developer and his much less geeky wife: more»

  • Ted Neward

    Enterprise, Virtual Machine and Language Wonk

    ... Corey Vidal, you have outdone every YouTube video I've ever seen, and I was a hug more»

  • Pratik Patel

    Enterprise Architect

    SpringSource today announced that it has purchased G2One, the folks who have been driving the development of Groovy and Grails. The following... more»

  • Graeme Rocher

    Project Lead of the Grails Project & CTO of G2One

    You may have already read about it in the various news outlets and blogs covering the announcement, but if you haven’t I’m excited to spread... more»

  • Andrew Glover

    Co-author of "Continuous Integration"

    more»

  • Matt Raible

    Creator of AppFuse and author of Spring Live

    This morning, my co-workers and I discovered that Link edIn decided to trim 10% of its employees. The Denver Offi more»

  • Jared Richardson

    Agile coach and co-author of Ship It

    Jurgen Appelo has an ongoing interview series on his blog. He's published a lot of very smart people and I'm honored to squeak in too! ;) more»

  • David Bock

    Principal Consultant, CodeSherpas Inc.

    I have been setting up a rock-solid server cluster for a client and ran into an interesting issue trying to install Phusion Passenger onto... more»

  • Pramod Sadalage

    Co-author of "Refactoring Databases:Evolutionary Database Development"

    Consider this Hibernate mapping @Column(name = "qReferenceId") public Long getQReferenceId() { return qReferenceId; more»

  • Craig Walls

    Author of Spring in Action

    At one time not too long ago, I wasn't a big fan of annotations. But then I let my guard down and even started liking them. But now I'm... more»

  • Scott Leberknight

    Chief Architect at Near Infinity

    In late 2006 Neal Ford wrote about Polyglot Programming and predicted more»

  • Kenneth Kousen

    President of Kousen IT, Inc.

    In this entry in my “Making Swing Groovy” series, I want to talk about threading issues. Specifically, more»

  • Venkat Subramaniam

    Founder of Agile Developer, Inc.

    I wrote a four part article for Java World on creating DSLs in Java and Groovy. For your convenience, I decided to list the links to those... more»

  • Jason Harwig

    Senior Software Engineer at Near Infinity

    The most popular entry I've written at Near Infinity has been the more»

  • John Heintz

    Principal Consultant with New Aspects of Software

    In a recent discussion interview questions came up, here's my favorite one.To set some context this question is designed to gauge the abst more»

  • Mark Johnson

    Director of Consulting at CGI

    At the Columbus NFJS show held on July 25-27th during one of the BOF sessions Dave Bock, Scott Davis and I discussed unit tests vs functional... more»

  • Joseph Nusairat

    Author of Beginning JBoss Seam & Co-Author of Beginning Groovy & Grails

    Well i am assuming Apress has the most random site in the world at times.But today only they have our recent book, Beginning Groovy & Grai more»

  • Keith Donald

    Lead of Spring Web and Creator of Spring Web Flow

    I am pleased to announce that Developing Rich Web Applications with Spring, a three-day bootcamp lead by SpringSource engineers on web... more»

  • Vladimir Vivien

    Software Engineer / Consultant

    Judging from the list of features that will be included in NetBeans 6.5, more»

  • Pete Behrens

    Organizational Agility Coach

    Marti nig & Associates Methods & Tools group recentl more»

  • Brian Sam-Bodden

    Java author, Ruby geek and Open Source Advocate

    In this installment we are going to build the Dashboard page of the Tempo application. T more»

  • Mark Fisher

    Spring Integration Lead

    In my recent post, I had mentio more»

  • Ron Bodkin

    Chief Software Architect, Quantcast

    I'm looking forward to speaking at The Rich Web Experience conference in San Jose next month. The event runs from September 7th through 9th.... more»

  • Mark Goodwin

    Web Application Security Specialist

    We've already looked at one of the two big problems posed by anti DNS pinning on Java applets; because there's rebinding on the applet and... more»

  • Scott Davis

    Author of "Groovy Recipes" & TDD Expert

    Every time I see a live show at the Denver Botanic more»

  • Romain Guy

    Java User Interface expert.

    more»

  • Ramnivas Laddad

    Author of AspectJ in Action, Principal at SpringSource

    InfoQ.com has published my AOP myths and realities talk recorded at a No Fluff Just Stuff conference. InfoQ.com founded by Floyd Marine more»

  • David Geary

    Author of Graphic Java and co-author of Core JSF

    The 2006 NFJS tour kicked off t more»

  • Kito Mann

    Editor-in-chief of JSF Central and the author of JSF in Action

    One of the enhancements added for JSF 1.2 was update of the MethodExpression signature for the action attribute of h:command{Link,Button}. In... more»

  • Jason Hunter

    Author of Java Servlet Programming

    I just posted the JDOM 1.1 release for download. This release includes about 20 improvements and bug fixes. more»

Java.next #2: Java Interop

Posted by: Stuart Halloway on 08/12/2008

This is Part Two of a series of articles on Java.next. In Part Two, I will look at how Java.next languages interoperate with Java.

Java interop is trivial in all of the Java.next languages. We have Java itself to thank for this--the Java Virtual Machine Specification makes it easy for other languages to reflect against and call Java code.

A Swing example

As a first example, consider calling into the Java Swing API to create an application [1] that has

  • a frame
  • button
  • a button handler that responds with a model dialog

For starters, here is the application in plain old Java:

// Java
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Swing {
  public static void main(String[] args) {
    JFrame frame = new JFrame("Hello Swing");
    JButton button = new JButton("Click Me");

    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        JOptionPane.showMessageDialog(null,
            String.format("<html>Hello from <b>Java</b><br/>" +
                          "Button %s pressed", event.getActionCommand()));
      }
    });
    frame.getContentPane().add(button);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
  }
}

Below, I will present the same Swing application, ported to the Java.next languages. Please take note of two things about these examples:

  • For this post, I am presenting the languages in order of increasing syntactic distance from Java. This makes sense for porting a simple example from the well-known to the increasingly unfamiliar.
  • The ports below are not best practice in the Java.next languages. They are deliberately simplistic, so that I can focus on Java interop. In later installments of this series I will show more idiomatic Java.next code.

Groovy Swing example

Groovy is the Java.next language that looks most like Java. Here is the same example in Groovy:

// Groovy
import javax.swing.JFrame
import javax.swing.JButton
import javax.swing.JOptionPane
import java.awt.event.ActionListener

frame = new JFrame("Hello Swing")
button = new JButton("Click Me")

button.addActionListener({
  JOptionPane.showMessageDialog(null, """<html>Hello from <b>Groovy</b>
Button ${it.actionCommand} pressed""")
} as ActionListener) 
frame.contentPane.add button

frame.defaultCloseOperation = JFrame.EXIT_ON_CLOSE
frame.pack()
frame.visible = true

If you compare this to the Java example, it is almost the same code, minus a bunch of unnecessary ceremony. The Groovy version lets us omit:

  • semicolons
  • type declarations
  • most parentheses
  • get and set for property access

The most important benefit, however, comes in the action listener. The Groovy version sports

  • a multiline string (delimited by """)
  • string interpolation of it.actionCommand (inside ${})
  • no need to write an anonymous inner class, simply pass an anonymous function

Since this post is about Java interop I will state the obvious: From Groovy, Java interop is entirely trivial.

Scala Swing example

Next, let's look at the Scala version:

// Scala (almost right, see below)
import javax.swing._; 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

object HelloWorld extends JFrame("Hello Swing") {
  def showButtonMessage(msg: String)  =       
    JOptionPane.showMessageDialog(null, String.format("""<html>Hello from <b>Scala</b>.
Button %s pressed""", Array(msg)));

  def main(args: Array[String]) =
  {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
    val button = new JButton("Click Me")
    button.addActionListener((e:ActionEvent) => 
      showButtonMessage(e.getActionCommand.toString))
    getContentPane.add(button)
    pack;
    setVisible(true);
  }
}

The Scala version offers many of the same advantages over Java that the Groovy version provided:

  • fewer type declarations than Java
  • fewer semicolons
  • fewer parentheses

We also see a few items unique to Scala:

  • In Scala, the import wildcard is _, not *. In Scala, * is a valid identifier. (Scala's punctuation-friendly identifiers will be a big advantage later when I am writing DSLs.)
  • Since we only need one, we declare an object instead of a class.
  • Our object extends JFrame, and Scala lets us call the JFrame constructor inline, instead of having to declare a separate constructor.

Again, the most important differences are in the action listener. Like Groovy, Scala lets us skip the anonymous inner class ritual, and simply pass a function:

button.addActionListener((e:ActionEvent) => 
  showButtonMessage(e.getActionCommand.toString))

That looks great, except I cheated a little. Scala's implementation of strong typing won't automatically coerce a function into an ActionListener, so the above code won't compile out of the box. Fortunately, Scala's implicit conversions let us have our cake and eat it too: strong typing plus much of the syntactic convenience of a looser type system. All we have to do is tell Scala the the conversion is legal:

// Yes, we can
implicit def actionPerformedWrapper(func: (ActionEvent) => Unit) = 
  new ActionListener { def actionPerformed(e:ActionEvent) = func(e) }

With this one-time setup in place, we can now pass a function where an ActionListener is expected.

There seem to be several projects to wrap Swing in more idiomatic Scala. Using one of these libraries you should be able to get a syntax cleaner than the sample code here. See ScalaGUI for one example.

From Scala, Java interop is trivial.

JRuby Swing example

Let's see how JRuby fares:

include Java
import javax.swing.JFrame
import javax.swing.JButton
import javax.swing.JOptionPane
import java.awt.event.ActionListener

button = JButton.new "Click Me"
button.add_action_listener(ActionListener.impl { |m,evt|
  JOptionPane.showMessageDialog(nil, <<-END)
<html>Hello from <b>JRuby</b>. 
Button '#{evt.getActionCommand()}' clicked.
END
})

frame = JFrame.new "Hello Swing"
frame.content_pane.add button
frame.default_close_operation = JFrame::EXIT_ON_CLOSE
frame.pack
frame.visible = true

If you compare this to the earlier Groovy example, you will see almost exactly the same feature set:

  • fewer type declarations
  • fewer semicolons
  • fewer parentheses
  • simplified property access (no get or set)
  • a multiline string (delimited by END)
  • string interpolation of evt.getActionCommand (the stuff inside #{})

The action listener callback is simplified, but in a slightly different way. For implementing a Java interface, JRuby provides the impl method, which implements an interface and passes all methods to a block:

button.add_action_listener(ActionListener.impl { |method,evt|
  # do stuff
END

This is more verbose than the Groovy technique, because it is more general: the unused method parameter allows for interfaces with more than one method.

Does this mean I am stuck with a verbose, general approach that is overkill for my needs? Absolutely not. In Java.next, you bend languages to your will (not the other way around). So, if you want JRuby to support a more Groovy-like syntax, roll it yourself! (See the Profligacy project for an example.) Ruby's flexibility has encouraged a lot of experimentation with alternate syntaxes for Java interop. See JRUBY-903 for some of the history.

In the JRuby example I used Ruby conventions for method names, even on Java objects:

# Ruby
frame.content_pane

Java programmers expect camel case. As a convenience, JRuby supports both naming conventions:

# Groovy, Scala, or JRuby
frame.contentPane

From JRuby, Java interop is trivial.

Clojure Swing example

Here is the Clojure version:

; Clojure 
(import '(javax.swing JFrame JButton JOptionPane))
(import '(java.awt.event ActionListener))

(let [frame (new JFrame "Hello Swing")
      button (new JButton "Click Me")]
  (.addActionListener 
   button
   (proxy [ActionListener] []
     (actionPerformed 
      [evt]
      (.showMessageDialog 
       JOptionPane 
       nil, 
       (str "<html>Hello from <b>Clojure</b>.<br/> Button " (.getActionCommand evt) " clicked.")))))

  (.. frame (getContentPane) (add button))
  (doto frame
    (setDefaultCloseOperation (. JFrame EXIT_ON_CLOSE))
    (pack)
    (setVisible true)))

Because Clojure is a Lisp, the syntax is radically different from the others. This deserves hours of discussion, or none. Since my focus here is on Java interop, I am going to save The Great Parenthesis Debate for a later entry in this series. For now, let us suspend judgment on syntax, and focus exclusively on the Java interop.

Importing Java classes is easy. import takes a list. The first element of the list is a package, and the remaining elements are classes to add to the current namespace. Note that this allows the import of multiple classes in a single line.

(import '(javax.swing JFrame JButton JOptionPane))

Creating a Java instance is easy. Use the (new class &args) form.

(new JFrame "Hello Swing")

There are multiple ways to call methods on a Java class. If you want to call a single method, you can use the (.methodName obj &args) form. obj can be a class or an instance.

(.showMessageDialog JOptionPane nil "A message")

Sometimes you want to chain multiple calls together. Where in Java you would say x.y().z(), in Clojure you can use the (.. x (y) (z)) form.

(.. frame (getContentPane) (add button))

The last three method calls in our example are all on the same frame object. With Clojure's doto form, you can perform multiple operations on an object without having to repeat the object each time.

(doto frame
  (setDefaultCloseOperation (. JFrame EXIT_ON_CLOSE))
  (pack)
  (setVisible true)))

As with the other examples, the action listener is the most interesting part. In Clojure, proxy will dynamically create a Java instance [2], allowing you to implement interfaces and methods as needed.

(proxy [ActionListener] []
  (actionPerformed [evt] {do stuff here...}))

As with JRuby, this solution is more general, and requires more syntax, than the Groovy approach. Also as with JRuby, you can easily roll your own syntax.

From Clojure, Java interop is trivial.

Try this at home

The interop story in Java.next is almost boring: It Just Works. So to spice things up a little, here is an exercise in rolling your own constructs, inspired by the examples above. Consider Clojure's import, which can import multiple Java classes in a single line of code.

(import '(javax.swing JFrame JButton JOptionPane))

Why can't this be even more general? Try your hand at writing a custom import function in one of the Java.next languages. Some useful features might be

  • import all the classes in a JAR
  • import all the classes in the intersection of a package and a JAR
  • import only interfaces
  • import all classes macthing some criteria
  • import all classes except those matching some criteria

Let me know what you come up with, and I will link to it here.

Conclusion

In the examples above, I have demonstrated how all of the Java.next libraries can trivially interoperate with Java. Each of examples called the Swing library with fewer lines of code than the Java version. More importantly, the Java.next versions capture the essence of the program with less ceremony.

Seamless interoperation with Java should not be the primary yardstick when measuring Java.next languages, because they all get it right. There are complexities and corner cases beyond what I have shown here, in all of the Java.next languages. But I consider the Java interop problem to be basically solved.

In these first two articles, I have stayed fairly close to Java style while demonstrating Java.next language features. With that groundwork in place, it is time to start using idiomatic Java.next. In the next installment of the Java.next series, we will look at how the Java.next languages support Domain-Specific Languages.

Notes

  • This series is taken from the JVM Language Shootout talk. Check the schedule for a talk near you.
  • Suggestions for improving the code samples above are most welcome.
  • Thanks to Jason Rudolph, Glenn Vanderburg, and Greg Vaughn for reading an earlier draft of this article.

Footnotes

  1. I took the Swing application example from the JRuby samples, and ported it to the other Java.next languages.
  2. Clojure's proxy creates classes as necessary behind the scenes. In Java.next, the dichotomy of class and object is not constantly center stage.

be the first to rate this blog


About Stuart Halloway

Stuart Halloway is the CEO of Relevance, Inc. (www.thinkrelevance.com). With co-founder Justin Gehtland, Stuart helps enterprises adopt emerging best practices such as Ruby on Rails. Justin and Stuart founded the Streamlined Framework (www.streamlinedframework.org), and authored Rails for Java Developers. Stuart is also the author of Component Development for the Java Platform. Prior to founding Relevance, Stuart was the Chief Architect at Near-Time, and the Chief Technical Officer at DevelopMentor.