3
votes

Invoking a static Java method in Clojure is smooth; no problem. But when I invoke a non-static method, it throws an error, although I have tried several variations for dot (.) notation, as explained in Clojure Interop documentation.

The Java class:

public class CljHelper {

  public void test(String text) {
    System.out.println(text);
  }

}

The Clojure code:

(ns com.acme.clojure.Play
  (:import [com.acme.helpers CljHelper]))

(. CljHelper test "This is a test")  

The error:

java.lang.IllegalArgumentException: No matching method: test

This is another attempt, which makes the Java method to be executed but throws an error right after:

(defn add-Id
  [x]
  (let [c (CljHelper.)]
    ((.test c x))))        ;;; java.lang.NullPointerException: null in this line

(add-Id "id42")

The error:

java.lang.NullPointerException: null
2
Remove the outer parens ((.test c x)) - you are calling the result of test, which is nil - parens always have meaning and can not be added to make things more clear like in curly-brace-langs.cfrick
yes, you're right; there was an extra set of parens.Eduardo MC

2 Answers

6
votes

You have two different issues here. In the first example you're trying to invoke a method on the class CljHelper. You should be calling it on the instance, not the class.

(.test (CljHelper.) "This is a test")

For the second example, you have an extra set of parentheses. So, you're correctly calling the method test, but then you are taking the result, which is null, and attempting to call that as a function. So just remove the parentheses.

(defn add-id
  [x]
  (let [c (CljHelper.)]
    (.test c x)))
4
votes

Here is the easiest way to do it. Make a java class Calc:

package demo;

public class Calc {
  public int answer() {
    return 42;
  } 
}

and call it from Clojure:

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:import [demo Calc]))

(let [c (Calc.)]                   ; construct an instance of Calc
  (println :answer (.answer c)))   ; call the instance method

with result:

:answer 42

You can clone a template Clojure project to get started.