Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use a scala class which implements a java interface from Java?

I'm learning Scala and was curious if it would be possible to:

  1. Create an object which implements a Java interface in Scala
  2. Compile the object into a class file and jar it
  3. Use the object from Java

I want to implement a custom lucene query parser in scala and be able to let others access it from a java application.

like image 238
tommy chheng Avatar asked Feb 27 '10 22:02

tommy chheng


People also ask

Can Java and Scala work together?

Is it possible to mix Scala and Java code? Yes, there is the ability to mix both types of code. It is possible to create an SBT project, put Scala code in src/main/scala and java code in src/main/java in the same project and make it work.

Can we use Java libraries in Scala?

Scala is designed to work smoothly with Java and Java libraries like JMSL. This is clearly evident in how Scala picks up the same CLASSPATH environment variable Java uses, so if the Java library you wish to use is already there in the CLASSPATH, then you're good to go.

Is trait in Scala same as interface in Java?

Like a class, Traits can have methods(both abstract and non-abstract), and fields as its members. Traits are just like interfaces in Java. But they are more powerful than the interface in Java because in the traits we are allowed to implement the members.

Can a class implement an interface Java?

To declare a class that implements an interface, you include an implements clause in the class declaration. Your class can implement more than one interface, so the implements keyword is followed by a comma-separated list of the interfaces implemented by the class.


2 Answers

I'm assuming that by "object" you actually mean "class". In any case, the answer is yes, you can do this. You will need to take advantage of the Scala/Java joint compiler if you want this all in the same project. For example:

public interface Parser {
    public TokenIterator parse(InputStream is);
}

Then in Scala:

class ParserImpl extends Parser {
  def parse(is: InputStream) = ...
}

Finally, in Java again:

public class Consumer {
    public static void main(String[] args) {
        Parser p = new ParserImpl();       // just like a Java class!
        ...
    }
}

If all of these source files are in the same project, then you will want to compile them using the following invocation of commands:

$ scalac *.scala *.java
$ javac -classpath . *.java

The first command invokes the Scala/Java joint compiler, which will compile the Scala sources and just enough of the Java sources to satisfy any dependencies. The second command invokes the Java compiler with the recently-compiled Scala classes on the classpath.

like image 192
Daniel Spiewak Avatar answered Sep 30 '22 17:09

Daniel Spiewak


I have implemented a custom org.apache.solr.handler.RequestHandlerBase and custom org.apache.solr.request.QueryResponseWriter in Scala 2.8 with Java 1.6.0 and Solr 1.4.0. I am not sure of the Lucene version Solr 1.4.0 is using but I would assume a fairly recent one. Anyway, I packaged the class files generated by Scala in a jar and Solr was able to load it just fine. So what you are trying to do is possible.

I would say the main thing to overcome is to convert from Java collection objects like List and Vector to Scala collection objects and vice versa. scala.collection.JavaConversions in Scala 2.8.0 will probably be your friend.

One other thing, if you need to override a method like getBooleanQuery, you may need to add [_] to make Scala compile (code not tested - but since it took me a while to figure that kind of stuff out when I started Scala, I thought I'd share):

override def getBooleanQuery(clauses: java.util.List[_]): Query = { ... }

Edit:: One more thing about the joint compilation. Daniel's information on how to joint compile is useful. You may not immediately need it though, as very likely, you just need to have scalac know the path to the Lucene jar files, then package your class in a new jar, and have your jar file used at runtime in the deployed environment.

like image 39
huynhjl Avatar answered Sep 30 '22 17:09

huynhjl