Share your thoughts in the 2020 Clojure Community Survey!

Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by

I'm trying to replicate a Java interface using gen-interface, which has some Java classes implementing it where they define their overrides as throws Exception. But I do not know how in Clojure to specify that in the signature?

Example:

public class Someclass implements MyInterface {
  public void perform(CommandLine line) throws Exception {
     ...
  }
}

-

(gen-interface
 :name some.place.MyInterface
 :methods [[perform [org.apache.commons.cli.CommandLine] void]])

This fails with in javac with: overridden method does not throw Exception

Is there any way to create an interface which declares a throws clause on the methods in Clojure using gen-interface?

2 Answers

+1 vote
by
selected by
 
Best answer

This is not supported and is unlikely to be added.

The best option to create custom interfaces like this is to define them in Java.

0 votes
by

I don't think either gen-class or gen-interface support checked exceptions. I could be wrong about that though. Why do you want a general "throws Exception" declaration?

Personally my approach (because I think checked exceptions were a poor idea) is whenever I have code that could throw one I just wrap it in a try catch that wraps the checked exception in a RuntimeException and throws that.

by
It's mostly for backward compatibility. There's a lot of existing Java code that use that interface and implement it where their declaration throws exceptions and their implementations throw checked exceptions. Would be a lot of work to go and change all of it.

And the reason I am re-writing the interface in Java, is because I want to implement this interface in Clojure, but the Java code already uses Clojure, so there is a circular dependency, where Java needs Clojure to be built first, and Clojure needs Java to be built first. I could extract it out into a 3rd library, but that's also annoying, so I was hoping I could just create the interface in Clojure.
by
Could you post some more example code of what you're trying to achieve? Clojure forbids circular dependencies for namespaces, but they're actually fine usually in java interface/class land
by
It's at the build level. I have a mixed Clojure/Java project. Java calls the Clojure code through some gen-class, thus I have to build Clojure first so that when Java compiles it finds the gen-classes to link against. But, there's a place where I want to have a Clojure gen-class that implements a Java interface. At this point, when Clojure compiles the gen-class, it fails, because it can't find the interface class file, because Java hasn't been built yet.

So I tried moving the interface to Clojure land, but it defines methods that throw exceptions, so it seems that's not possible.
by
You can control your build order more granularly than that using leiningen or boot. Compile the specific clojure code that generates your gen-class, then the java, then the rest of the clojure.
...