Consuming scala code from java

54 views
Skip to first unread message

rklaehn

unread,
Sep 5, 2011, 8:21:35 AM9/5/11
to Scala IDE User, Roland Kuhn
Hi all,

I am currently having some problems with scala/java interop. The
situation is that we have a very large code base (>100k LOC) where we
would like to start using scala in some places.

We have had no problems consuming the java code from scala, as
expected. But now I have some scala code that we would also like to
use from java. This works fine for the most trivial examples, but
causes a lot of trouble for more complex scenarios. I think I
understand most of the issues now. But is there some information on
how to design scala libraries so that they can be used as easily as
possible from java?

I have a simple toy project consisting of a scala project (called
Library) and a java project (called Consumer).
I am using eclipse Version: 3.7.0 Build id: I20110613-1736 with the
scala plugin "nightly build 2.0.0.nightly-29-20110922359-66d6c63".

First of all, it seems that when creating the java consumer project
and adding the scala library as a dependency it seems that I have to
add the scala-library.jar manually to the class path as an external
jar, even though scala-library 2.9.1 is listed under "bootstrap
entries" in the classpath section of the "Edit launch configuration
properties" dialog. Otherwise I get the infamous "Exception in thread
"main" java.lang.NoClassDefFoundError: scala/ScalaObject", and all
sorts of highlighting errors as well.

Second, invoking methods with array arguments and/or return types
produces errors in the highlighting. Nevertheless the whole thing
compiles, since it is valid java code. This is annoying even in a toy
project such as this, but it is extremely annoying when using scala
code from lots of places in the above mentioned 100kLOC of java code.
Is this related to this issue
http://groups.google.com/group/scala-ide-user/browse_thread/thread/2d03aa2dc82ad678
? Any idea when/if this will be fixed?

Third, apparently that generic classes using primitive types as type
arguments do not translate to java as I would expect. Does this have
something to do with @Specialized, and what's the best way around this
issue?


Here are the relevant methods in the library and the use from java:

package scalalibrary

object Library {

def makeArray : Array[Byte] = Array(1,2,3,4)

def length(a:Array[Byte]) = a.length

def tryMakeInt() : Option[Int] = Some(1)

def tryMakeString() : Option[String] = None
}

---

mport scalalibrary.*;

public class Consumer {
public static void main(String[] args) {

byte[] bytes = Producer.makeArray(); // produces highlighting
error, but compiles

int a = Producer.length(bytes); // produces highlighting error,
but compiles

scala.Option<String> w = Producer.tryMakeString(); // this
works

scala.Option<Integer> x = Producer.tryMakeInt(); // this
doesn't
}
}

iulian dragos

unread,
Sep 6, 2011, 6:02:13 AM9/6/11
to scala-i...@googlegroups.com, Roland Kuhn
On Mon, Sep 5, 2011 at 2:21 PM, rklaehn <rkl...@googlemail.com> wrote:
> First of all, it seems that when creating the java consumer project
> and adding the scala library as a dependency it seems that I have to
> add the scala-library.jar manually to the class path as an external
> jar, even though scala-library 2.9.1 is listed under "bootstrap
> entries" in the classpath section of the "Edit launch configuration
> properties" dialog. Otherwise I get the infamous "Exception in thread
> "main" java.lang.NoClassDefFoundError: scala/ScalaObject", and all
> sorts of highlighting errors as well.

In principle this should not be necessary. Does your project have the
Scala nature?

> Second, invoking methods with array arguments and/or return types
> produces errors in the highlighting. Nevertheless the whole thing
> compiles, since it is valid java code. This is annoying even in a toy
> project such as this, but it is extremely annoying when using scala
> code from lots of places in the above mentioned 100kLOC of java code.
> Is this related to this issue
> http://groups.google.com/group/scala-ide-user/browse_thread/thread/2d03aa2dc82ad678
> ? Any idea when/if this will be fixed?

It looks like the same issue. I can't promise it will be in the next
beta, but we'll keep it in mind.

In general, it's almost impossible to support a true Java view for
Scala code, in the way the Eclipse Java presentation compiler expects
it. There are simply too many cases where there's no direct
translation of a Scala entity to a Java entity (for example, traits).
In such cases, you'll notice these incompatibilities: the builder will
work fine, but the presentation compiler will show red underlines. The
'presentation compiler' is the lightweight Java compiler that is used
for 'report error as you type', code completion, etc. If you have
Scala sources in your project, we 'interface' with the Java
presentation compiler by trying to offer a Java view from Scala source
code.

A better way would be, when possible, to depend on binary Scala
libraries: since the translation is already done to bytecode, you'll
see exactly what the builder will see.

> Third, apparently that generic classes using primitive types as type
> arguments do not translate to java as I would expect. Does this have
> something to do with @Specialized, and what's the best way around this
> issue?

Probably not, it's more likely to be an issue in our structure builder
for the Java presentation compiler. I think there's a ticket for this
issue as well, and I know Mirco looked into it but it wasn't easy.

cheers,
iulian

> Here are the relevant methods in the library and the use from java:
>
> package scalalibrary
>
> object Library {
>
>        def makeArray : Array[Byte] = Array(1,2,3,4)
>
>        def length(a:Array[Byte]) = a.length
>
>        def tryMakeInt() : Option[Int] = Some(1)
>
>        def tryMakeString() : Option[String] = None
> }
>
> ---
>
> mport scalalibrary.*;
>
> public class Consumer {
>        public static void main(String[] args) {
>
>            byte[] bytes = Producer.makeArray(); // produces highlighting
> error, but compiles
>
>            int a = Producer.length(bytes); // produces highlighting error,
> but compiles
>
>            scala.Option<String> w = Producer.tryMakeString(); // this
> works
>
>            scala.Option<Integer> x = Producer.tryMakeInt(); // this
> doesn't
>        }
> }
>

--
« Je déteste la montagne, ça cache le paysage »
Alphonse Allais

Reply all
Reply to author
Forward
0 new messages