This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Scala intepreter classloader + OSGi

18 replies
Romain
Joined: 2010-09-05,
User offline. Last seen 42 years 45 weeks ago.

Hi Guys,

I am developing an OSGi application based on equinox (www.openmole.org).
The user interface is for now a groovy scripting environment. We plan to
migrate from groovy shell to a scala interpreter loop, but we are
encountering problems to integrate the scala interpreter in our
application. Basically the code we are trying is the following:

> val settings = new scala.tools.nsc.Settings()
> // settings.usejavacp.value = true
> //settings.classpath.value = "plugins/org.scala-lang.scala-2.8.0.jar"
> val interpreter = new scala.tools.nsc.InterpreterLoop()
> interpreter.main(settings)

When we launch the interpreter we get the following message:

> Failed to initialize compiler: object scala not found.
> ** Note that as of 2.8 scala does not assume use of the java classpath.
> ** For the old behavior pass -usejavacp to scala, or if using a Settings
> ** object programatically, settings.usejavacp.value = true.

We have tried to append the scala jar in the classpath, it works but
then we cannot access our businesses classes. We cannot put all our
business jar into the classpath for several reasons and we want to load
the classes through the OSGi class loaders (because thanks to OSGi we
have several version of the same classes, because we rely on the OSGi
activation process, because the load the classes in the plugins and
their dependencies is dynamic...).

Any idea how I can tell the scala Interpreter to use a given classloader
instead of it's default one?

Cheers,
Romain

Michael
Joined: 2009-02-23,
User offline. Last seen 20 weeks 1 day ago.
Re: Scala intepreter classloader + OSGi

> Any idea how I can tell the scala Interpreter to use a given classloader
> instead of it's default one?
>

Romain,

I've implemented basically the same thing for Apache Sling a while ago [1].
Unfortunately this is for Scala 2.7 still. However, I had to overcome the same
issues you are facing: getting the Scala compiler to load classes from the OSGi
class loaders. So maybe this is still helpful to you.

Michael

[1] http://people.apache.org/~mduerig/scala4scripting/

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Scala intepreter classloader + OSGi

On Sun, Sep 05, 2010 at 11:30:15AM +0200, Romain wrote:
> Any idea how I can tell the scala Interpreter to use a given
> classloader instead of it's default one?

Subclass it.

def classLoader: AbstractFileClassLoader
protected def parentClassLoader: ClassLoader

Romain
Joined: 2010-09-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Scala intepreter classloader + OSGi

Hello Paul,

I just tried this:

> println(classOf[scala.tools.nsc.Interpreter].getClassLoader.loadClass("scala.ScalaObject").toString)
>
> val interpreter = new scala.tools.nsc.Interpreter() {
> override def classLoader = new AbstractFileClassLoader(virtualDirectory, classOf[scala.tools.nsc.Interpreter].getClassLoader)
> }
>
> interpreter.interpret("println(\"hello\")" )

But it is not working:

> interface scala.ScalaObject
>
> Failed to initialize compiler: object scala not found.
> ** Note that as of 2.8 scala does not assume use of the java classpath.
> ** For the old behavior pass -usejavacp to scala, or if using a Settings
> ** object programatically, settings.usejavacp.value = true.

Have I done something the wrong way?

Cheers,
Romain

Le dimanche 05 septembre 2010 à 07:45 -0700, Paul Phillips a écrit :
> On Sun, Sep 05, 2010 at 11:30:15AM +0200, Romain wrote:
> > Any idea how I can tell the scala Interpreter to use a given
> > classloader instead of it's default one?
>
> Subclass it.
>
> def classLoader: AbstractFileClassLoader
> protected def parentClassLoader: ClassLoader
>

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Scala intepreter classloader + OSGi

On Sun, Sep 05, 2010 at 07:18:12PM +0200, Romain wrote:
> > Failed to initialize compiler: object scala not found.
> > ** Note that as of 2.8 scala does not assume use of the java classpath.
> > ** For the old behavior pass -usejavacp to scala, or if using a Settings
> > ** object programatically, settings.usejavacp.value = true.
>
> Have I done something the wrong way?

I sense the error message you quoted is unclear in some way, but you'll
have to tell me what way that is. Look at the constructors for
Interpreter, note that you're not supplying a Settings instance, re-read
the message.

Romain
Joined: 2010-09-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Scala intepreter classloader + OSGi

I don't know if it is unclear... For what I understand the scala
compiler is looking for "ScalaObject", isn't it?

That's why I tried to provide the Interperter with a classloader that is
able to load this class.

For the settings, if I provide a settings with the proposed option:

> println(classOf[scala.tools.nsc.Interpreter].getClassLoader.loadClass("scala.ScalaObject").toString)
>
> val settings = new scala.tools.nsc.Settings
> settings.usejavacp.value = true
>
>
> val interpreter = new scala.tools.nsc.Interpreter(settings) {
> override def classLoader = new AbstractFileClassLoader(virtualDirectory, classOf[scala.tools.nsc.Interpreter].getClassLoader)
> }
>
> interpreter.interpret("println(\"hello\")" )

I end up with exactly the same behavior: the scala code println(\"hello
\") is not being interpreted because of the error.

Romain

Le dimanche 05 septembre 2010 à 10:43 -0700, Paul Phillips a écrit :
> On Sun, Sep 05, 2010 at 07:18:12PM +0200, Romain wrote:
> > > Failed to initialize compiler: object scala not found.
> > > ** Note that as of 2.8 scala does not assume use of the java classpath.
> > > ** For the old behavior pass -usejavacp to scala, or if using a Settings
> > > ** object programatically, settings.usejavacp.value = true.
> >
> > Have I done something the wrong way?
>
> I sense the error message you quoted is unclear in some way, but you'll
> have to tell me what way that is. Look at the constructors for
> Interpreter, note that you're not supplying a Settings instance, re-read
> the message.
>

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Scala intepreter classloader + OSGi

On Sun, Sep 05, 2010 at 07:58:44PM +0200, Romain wrote:
> I don't know if it is unclear... For what I understand the scala
> compiler is looking for "ScalaObject", isn't it?

Plus or minus. It means the classpath doesn't include the scala jars.
Here is code which works fine run directly. I threw in a println to
output java.class.path since I'm assuming that's what you're missing
with your classloader setup. The advice to usejavacp is only useful if
you have a useful javacp. Otherwise you're going to have to set the
classpath up yourself. You can see below what constitues a functional
compiler classpath.

// self-contained compilable source always preferred
import scala.tools.nsc._
import interpreter.AbstractFileClassLoader

object Test {
val settings = new Settings
settings.usejavacp.value = true

val interpreter = new Interpreter(settings) {
override def classLoader = new AbstractFileClassLoader(
virtualDirectory,
classOf[scala.tools.nsc.Interpreter].getClassLoader
)
}

def main(args: Array[String]): Unit = {
println("java.class.path = " + System.getProperty("java.class.path"))
interpreter.interpret("println(\"hello\")" )
}
}

% scala Test
java.class.path = /scala/inst/scala-2.8.0.final/lib/jline.jar:/scala/inst/scala-2.8.0.final/lib/scala-compiler.jar:/scala/inst/scala-2.8.0.final/lib/scala-dbc.jar:/scala/inst/scala-2.8.0.final/lib/scala-library.jar:/scala/inst/scala-2.8.0.final/lib/scala-swing.jar:/scala/inst/scala-2.8.0.final/lib/scalap.jar
hello

Romain
Joined: 2010-09-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Scala intepreter classloader + OSGi

I understand. I have tried it and manage to get the Interpreter to work
in this simple example but we can't rely on this solution. I want to use
scala interpreter as a scripting interface for our application, that is
running in an OSGi environment. So we need to access our business
classes from the interpreter. In order for the OSGi application to work
classes must be loaded through the classloaders. They are several
reasons why we can't use a classpath here:
- we have several versions of the same classes (because of dependencies
we don't manage) it is fine in OSGi but they will conflict in the
classpath
- we use OSGi bundle activation mechanisms which relies on classloading
hooks
- the application is pluggable and OSGi bundle could be loaded and
unloaded dynamically.

This is not working with the subclassing solution:

> val settings = new scala.tools.nsc.Settings
> settings.usejavacp.value = true
> settings.classpath.value = "plugins/org.scala-lang.scala-2.8.0.jar"
>
>
> val interpreter = new scala.tools.nsc.Interpreter(settings) {
> override def classLoader = new AbstractFileClassLoader(virtualDirectory, classOf[org.openmole.ui.console.Application].getClassLoader)
> }
>
> interpreter.interpret("println(\"hello\"); import org.openmole.ui.console.Application;" )
>

This produces an error:

> interface scala.ScalaObject
> :5: error: value openmole is not a member of package org
> println("hello"); import org.openmole.ui.console.Application;

Is there a solution to use a java classloader to load the classes in the
scala interpreter ?

Romain

Le dimanche 05 septembre 2010 à 12:25 -0700, Paul Phillips a écrit :
> On Sun, Sep 05, 2010 at 07:58:44PM +0200, Romain wrote:
> > I don't know if it is unclear... For what I understand the scala
> > compiler is looking for "ScalaObject", isn't it?
>
> Plus or minus. It means the classpath doesn't include the scala jars.
> Here is code which works fine run directly. I threw in a println to
> output java.class.path since I'm assuming that's what you're missing
> with your classloader setup. The advice to usejavacp is only useful if
> you have a useful javacp. Otherwise you're going to have to set the
> classpath up yourself. You can see below what constitues a functional
> compiler classpath.
>
> // self-contained compilable source always preferred
> import scala.tools.nsc._
> import interpreter.AbstractFileClassLoader
>
> object Test {
> val settings = new Settings
> settings.usejavacp.value = true
>
> val interpreter = new Interpreter(settings) {
> override def classLoader = new AbstractFileClassLoader(
> virtualDirectory,
> classOf[scala.tools.nsc.Interpreter].getClassLoader
> )
> }
>
> def main(args: Array[String]): Unit = {
> println("java.class.path = " + System.getProperty("java.class.path"))
> interpreter.interpret("println(\"hello\")" )
> }
> }
>
> % scala Test
> java.class.path = /scala/inst/scala-2.8.0.final/lib/jline.jar:/scala/inst/scala-2.8.0.final/lib/scala-compiler.jar:/scala/inst/scala-2.8.0.final/lib/scala-dbc.jar:/scala/inst/scala-2.8.0.final/lib/scala-library.jar:/scala/inst/scala-2.8.0.final/lib/scala-swing.jar:/scala/inst/scala-2.8.0.final/lib/scalap.jar
> hello
>

Michael
Joined: 2009-02-23,
User offline. Last seen 20 weeks 1 day ago.
Re: Scala intepreter classloader + OSGi

Romain reuillon.org> writes:

>
> This produces an error:
>
> > interface scala.ScalaObject
> > :5: error: value openmole is not a member of package org
> > println("hello"); import org.openmole.ui.console.Application;
>
> Is there a solution to use a java classloader to load the classes in the
> scala interpreter ?

AFAIU this is caused by Scala compiler not being able to access that class at
compile time. The class loader is only used to by the interpreter for loading
classes at execution time. When compiling source the Scala compiler needs to
read the binary of the class files. A class loader won't do here! For Apache
Sling I implemented a file system abstraction on top of OSGi bundles and handed
this to the Scala interpreter. See the link I posted earlier for details.

Michael

Romain
Joined: 2010-09-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Scala intepreter classloader + OSGi

Thank you, I understand the difficulty of integrating scala in that
manner now. I had a look at your code. Why is it compatible only with
scala 2.7? Will it be updated for the needs of the apache sling project?
We would be very interesting having a library for that purpose, is there
any plan for making this bunch of code a maintained library?

Cheers,
Rom

Le dimanche 05 septembre 2010 à 21:50 +0000, Michael a écrit :
> Romain reuillon.org> writes:
>
> >
> > This produces an error:
> >
> > > interface scala.ScalaObject
> > > :5: error: value openmole is not a member of package org
> > > println("hello"); import org.openmole.ui.console.Application;
> >
> > Is there a solution to use a java classloader to load the classes in the
> > scala interpreter ?
>
> AFAIU this is caused by Scala compiler not being able to access that class at
> compile time. The class loader is only used to by the interpreter for loading
> classes at execution time. When compiling source the Scala compiler needs to
> read the binary of the class files. A class loader won't do here! For Apache
> Sling I implemented a file system abstraction on top of OSGi bundles and handed
> this to the Scala interpreter. See the link I posted earlier for details.
>
> Michael
>

Michael
Joined: 2009-02-23,
User offline. Last seen 20 weeks 1 day ago.
Re: Scala intepreter classloader + OSGi

> Why is it compatible only with
> scala 2.7? Will it be updated for the needs of the apache sling project?
> We would be very interesting having a library for that purpose, is there
> any plan for making this bunch of code a maintained library?

It is Scala 2.7 only since no one came around updating it to Scala 2.8 yet. Also
there is some discussion on where this implementation should live [1, 2] since
Apache Sling is not the right place. And finally there is an issue on the Scala
bug tracker [3].
Updating this to Scala 2.8 is in the back of my head for some time. However it
seems I wont have enough time at the moment.

Michael

[1] http://markmail.org/thread/fpd3ukqm3dhghwwc
[2] http://markmail.org/thread/mp6scm4ga4g4jz3q
[3] https://lampsvn.epfl.ch/trac/scala/ticket/874

Romain
Joined: 2010-09-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Scala interpreter classloader + OSGi

Hi Michael,

I am trying to use org.apache.sling.scripting.scala.script with jsr 223
in a test project. But I get the following exception:

> Exception in thread "main" scala.tools.nsc.MissingRequirementError: object scala not found.
> at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:517)
> at scala.tools.nsc.symtab.Definitions$definitions$.ScalaPackage(Definitions.scala:37)
> at scala.tools.nsc.symtab.Definitions$definitions$.ScalaPackageClass(Definitions.scala:38)
> at scala.tools.nsc.symtab.Definitions$definitions$.UnitClass(Definitions.scala:83)
> at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:789)
> at scala.tools.nsc.Global$Run.(Global.scala:604)
> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:126)
> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:142)
> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:152)
> at org.apache.sling.scripting.scala.ScalaScriptEngine$$anonfun$1.apply(ScalaScriptEngine.scala:113)
> at org.apache.sling.scripting.scala.ScalaScriptEngine$$anonfun$1.apply(ScalaScriptEngine.scala:113)
> at org.apache.sling.scripting.scala.ScalaScriptEngine.writeLocked(ScalaScriptEngine.scala:171)
> at org.apache.sling.scripting.scala.ScalaScriptEngine.eval(ScalaScriptEngine.scala:112)
> at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
> at fr.iscpif.testscalascript.App.main(App.java:19)

Do you have any idea why ?

Cheers,
Romain

PS:

My code is:

> import javax.script.ScriptEngine;
> import javax.script.ScriptEngineManager;
> import javax.script.ScriptException;
>
> /**
> * Hello world!
> *
> */
> public class App {
>
> public static void main(String[] args) {
> System.out.println("Hello World!");
>
> ScriptEngineManager mgr = new ScriptEngineManager();
> ScriptEngine jsEngine = mgr.getEngineByName("scala");
> try {
> jsEngine.eval("println(\"Hello, world from scala!\")");
> } catch (ScriptException ex) {
> ex.printStackTrace();
> }
>
> }
> }

And I build the application with the following maven script:

> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
> 4.0.0
>
> fr.iscpif
> testscalascript
> 1.0-SNAPSHOT
> jar
>
> testscalascript
> http://maven.apache.org
>
>
> UTF-8
>
>
>
>
> org.apache.sling
> org.apache.sling.scripting.scala.script
> 0.9.0-SNAPSHOT
>
>
> org.slf4j
> slf4j-api
> 1.6.1
>
>
> org.scala-lang
> scala-library
> 2.8.1
>
>
>
>
>
>
> maven.iscpif.fr
> ISCPIF repository
> http://maven.iscpif.fr/public-snapshots/
>
>
>

Le lundi 06 septembre 2010 à 08:39 +0000, Michael a écrit :
> > Why is it compatible only with
> > scala 2.7? Will it be updated for the needs of the apache sling project?
> > We would be very interesting having a library for that purpose, is there
> > any plan for making this bunch of code a maintained library?
>
> It is Scala 2.7 only since no one came around updating it to Scala 2.8 yet. Also
> there is some discussion on where this implementation should live [1, 2] since
> Apache Sling is not the right place. And finally there is an issue on the Scala
> bug tracker [3].
> Updating this to Scala 2.8 is in the back of my head for some time. However it
> seems I wont have enough time at the moment.
>
> Michael
>
> [1] http://markmail.org/thread/fpd3ukqm3dhghwwc
> [2] http://markmail.org/thread/mp6scm4ga4g4jz3q
> [3] https://lampsvn.epfl.ch/trac/scala/ticket/874
>

Michael
Joined: 2009-02-23,
User offline. Last seen 20 weeks 1 day ago.
Re: Re: Scala interpreter classloader + OSGi

Romain,

this is a class path issue: the Scala compiler doesn't find the Scala
library jar. There have been some changes between Scala 2.7 and 2.8:
AFAIK in 2.8 the environment class path (java.class.path) is not passed
to the compiler anymore.

You should be able to work around this by passing the -usejavacp to the
Scala compiler explicitly. This can be done by adding a "scala.settings"
key with a value of type scala.tools.nsc.Settings to the ScriptContext.
See the sources for ScalaScriptEngine and ScalaScriptEngineFactory for
more details.

Michael

On 5.1.11 17:19, Romain wrote:
> Hi Michael,
>
> I am trying to use org.apache.sling.scripting.scala.script with jsr 223
> in a test project. But I get the following exception:
>
>> Exception in thread "main" scala.tools.nsc.MissingRequirementError: object scala not found.
>> at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:517)
>> at scala.tools.nsc.symtab.Definitions$definitions$.ScalaPackage(Definitions.scala:37)
>> at scala.tools.nsc.symtab.Definitions$definitions$.ScalaPackageClass(Definitions.scala:38)
>> at scala.tools.nsc.symtab.Definitions$definitions$.UnitClass(Definitions.scala:83)
>> at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:789)
>> at scala.tools.nsc.Global$Run.(Global.scala:604)
>> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:126)
>> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:142)
>> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:152)
>> at org.apache.sling.scripting.scala.ScalaScriptEngine$$anonfun$1.apply(ScalaScriptEngine.scala:113)
>> at org.apache.sling.scripting.scala.ScalaScriptEngine$$anonfun$1.apply(ScalaScriptEngine.scala:113)
>> at org.apache.sling.scripting.scala.ScalaScriptEngine.writeLocked(ScalaScriptEngine.scala:171)
>> at org.apache.sling.scripting.scala.ScalaScriptEngine.eval(ScalaScriptEngine.scala:112)
>> at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
>> at fr.iscpif.testscalascript.App.main(App.java:19)
>
> Do you have any idea why ?
>
> Cheers,
> Romain
>
> PS:
>
> My code is:
>
>> import javax.script.ScriptEngine;
>> import javax.script.ScriptEngineManager;
>> import javax.script.ScriptException;
>>
>> /**
>> * Hello world!
>> *
>> */
>> public class App {
>>
>> public static void main(String[] args) {
>> System.out.println("Hello World!");
>>
>> ScriptEngineManager mgr = new ScriptEngineManager();
>> ScriptEngine jsEngine = mgr.getEngineByName("scala");
>> try {
>> jsEngine.eval("println(\"Hello, world from scala!\")");
>> } catch (ScriptException ex) {
>> ex.printStackTrace();
>> }
>>
>> }
>> }
>
> And I build the application with the following maven script:
>
>> > xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
>> 4.0.0
>>
>> fr.iscpif
>> testscalascript
>> 1.0-SNAPSHOT
>> jar
>>
>> testscalascript
>> http://maven.apache.org
>>
>>
>> UTF-8
>>
>>
>>
>>
>> org.apache.sling
>> org.apache.sling.scripting.scala.script
>> 0.9.0-SNAPSHOT
>>
>>
>> org.slf4j
>> slf4j-api
>> 1.6.1
>>
>>
>> org.scala-lang
>> scala-library
>> 2.8.1
>>
>>
>>
>>
>>
>>
>> maven.iscpif.fr
>> ISCPIF repository
>> http://maven.iscpif.fr/public-snapshots/
>>
>>
>>
>
>
>
> Le lundi 06 septembre 2010 à 08:39 +0000, Michael a écrit :
>>> Why is it compatible only with
>>> scala 2.7? Will it be updated for the needs of the apache sling project?
>>> We would be very interesting having a library for that purpose, is there
>>> any plan for making this bunch of code a maintained library?
>>
>> It is Scala 2.7 only since no one came around updating it to Scala 2.8 yet. Also
>> there is some discussion on where this implementation should live [1, 2] since
>> Apache Sling is not the right place. And finally there is an issue on the Scala
>> bug tracker [3].
>> Updating this to Scala 2.8 is in the back of my head for some time. However it
>> seems I wont have enough time at the moment.
>>
>> Michael
>>
>> [1] http://markmail.org/thread/fpd3ukqm3dhghwwc
>> [2] http://markmail.org/thread/mp6scm4ga4g4jz3q
>> [3] https://lampsvn.epfl.ch/trac/scala/ticket/874
>>
>
>

Romain
Joined: 2010-09-05,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Scala interpreter classloader + OSGi

Thank you, it is working like a charm. I am now going to test it with an
equinox OSGi environments and many dependencies. We presently use the
application with a groovy interface; hopefully we will be able to
migrate to a beautiful scala DSL.

Cheers,
Romain

PS: here is the code:

> package fr.iscpif.testscalascript
>
> import javax.script.ScriptContext
> import javax.script.ScriptEngine
> import javax.script.ScriptEngineManager
> import javax.script.ScriptException
> import javax.script.SimpleBindings
> import org.apache.sling.scripting.scala.ScalaScriptEngineFactory
> import scala.tools.nsc.Settings
>
> /**
> * Hello world!
> *
> */
> object App {
>
> def main(args: Array[String]) {
> println("Hello World!")
>
> val mgr = new ScriptEngineManager
> val engine = (new ScalaScriptEngineFactory).getScriptEngine
> val settings = new scala.tools.nsc.Settings
> settings.usejavacp.value = true
>
> engine.put(ScalaScriptEngineFactory.SCALA_SETTINGS, settings)
>
> val script = """
> package script {
> class Demo(args: DemoArgs) {
> println("Hello from scala")
> }
> }
> """
> engine.getContext.setAttribute("scala.script.class", "script.Demo", ScriptContext.ENGINE_SCOPE)
>
> try {
> engine.eval(script)
> //" package script {object Test {def main(args: Array[String]) = {println(\"Hello, world from scala!\")}}}")
> } catch {
> case ex => ex.printStackTrace
> }
>
> }
> }

Le mercredi 05 janvier 2011 à 17:54 +0100, Michael Dürig a écrit :
> Romain,
>
> this is a class path issue: the Scala compiler doesn't find the Scala
> library jar. There have been some changes between Scala 2.7 and 2.8:
> AFAIK in 2.8 the environment class path (java.class.path) is not passed
> to the compiler anymore.
>
> You should be able to work around this by passing the -usejavacp to the
> Scala compiler explicitly. This can be done by adding a "scala.settings"
> key with a value of type scala.tools.nsc.Settings to the ScriptContext.
> See the sources for ScalaScriptEngine and ScalaScriptEngineFactory for
> more details.
>
> Michael
>
> On 5.1.11 17:19, Romain wrote:
> > Hi Michael,
> >
> > I am trying to use org.apache.sling.scripting.scala.script with jsr 223
> > in a test project. But I get the following exception:
> >
> >> Exception in thread "main" scala.tools.nsc.MissingRequirementError: object scala not found.
> >> at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:517)
> >> at scala.tools.nsc.symtab.Definitions$definitions$.ScalaPackage(Definitions.scala:37)
> >> at scala.tools.nsc.symtab.Definitions$definitions$.ScalaPackageClass(Definitions.scala:38)
> >> at scala.tools.nsc.symtab.Definitions$definitions$.UnitClass(Definitions.scala:83)
> >> at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:789)
> >> at scala.tools.nsc.Global$Run.(Global.scala:604)
> >> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:126)
> >> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:142)
> >> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:152)
> >> at org.apache.sling.scripting.scala.ScalaScriptEngine$$anonfun$1.apply(ScalaScriptEngine.scala:113)
> >> at org.apache.sling.scripting.scala.ScalaScriptEngine$$anonfun$1.apply(ScalaScriptEngine.scala:113)
> >> at org.apache.sling.scripting.scala.ScalaScriptEngine.writeLocked(ScalaScriptEngine.scala:171)
> >> at org.apache.sling.scripting.scala.ScalaScriptEngine.eval(ScalaScriptEngine.scala:112)
> >> at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
> >> at fr.iscpif.testscalascript.App.main(App.java:19)
> >
> > Do you have any idea why ?
> >
> > Cheers,
> > Romain
> >
> > PS:
> >
> > My code is:
> >
> >> import javax.script.ScriptEngine;
> >> import javax.script.ScriptEngineManager;
> >> import javax.script.ScriptException;
> >>
> >> /**
> >> * Hello world!
> >> *
> >> */
> >> public class App {
> >>
> >> public static void main(String[] args) {
> >> System.out.println("Hello World!");
> >>
> >> ScriptEngineManager mgr = new ScriptEngineManager();
> >> ScriptEngine jsEngine = mgr.getEngineByName("scala");
> >> try {
> >> jsEngine.eval("println(\"Hello, world from scala!\")");
> >> } catch (ScriptException ex) {
> >> ex.printStackTrace();
> >> }
> >>
> >> }
> >> }
> >
> > And I build the application with the following maven script:
> >
> >> >> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
> >> 4.0.0
> >>
> >> fr.iscpif
> >> testscalascript
> >> 1.0-SNAPSHOT
> >> jar
> >>
> >> testscalascript
> >> http://maven.apache.org
> >>
> >>
> >> UTF-8
> >>
> >>
> >>
> >>
> >> org.apache.sling
> >> org.apache.sling.scripting.scala.script
> >> 0.9.0-SNAPSHOT
> >>
> >>
> >> org.slf4j
> >> slf4j-api
> >> 1.6.1
> >>
> >>
> >> org.scala-lang
> >> scala-library
> >> 2.8.1
> >>
> >>
> >>
> >>
> >>
> >>
> >> maven.iscpif.fr
> >> ISCPIF repository
> >> http://maven.iscpif.fr/public-snapshots/
> >>
> >>
> >>
> >
> >
> >
> > Le lundi 06 septembre 2010 à 08:39 +0000, Michael a écrit :
> >>> Why is it compatible only with
> >>> scala 2.7? Will it be updated for the needs of the apache sling project?
> >>> We would be very interesting having a library for that purpose, is there
> >>> any plan for making this bunch of code a maintained library?
> >>
> >> It is Scala 2.7 only since no one came around updating it to Scala 2.8 yet. Also
> >> there is some discussion on where this implementation should live [1, 2] since
> >> Apache Sling is not the right place. And finally there is an issue on the Scala
> >> bug tracker [3].
> >> Updating this to Scala 2.8 is in the back of my head for some time. However it
> >> seems I wont have enough time at the moment.
> >>
> >> Michael
> >>
> >> [1] http://markmail.org/thread/fpd3ukqm3dhghwwc
> >> [2] http://markmail.org/thread/mp6scm4ga4g4jz3q
> >> [3] https://lampsvn.epfl.ch/trac/scala/ticket/874
> >>
> >
> >
>

Michael
Joined: 2009-02-23,
User offline. Last seen 20 weeks 1 day ago.
Re: Re: Scala interpreter classloader + OSGi

Cool! Thanks for posting the code. I think it would make sense to set
usejavacp to true by default for the script engine. WDYT? I'll create an
issue for that.

Michael

On 5.1.11 19:20, Romain wrote:
> Thank you, it is working like a charm. I am now going to test it with an
> equinox OSGi environments and many dependencies. We presently use the
> application with a groovy interface; hopefully we will be able to
> migrate to a beautiful scala DSL.
>
> Cheers,
> Romain
>
> PS: here is the code:
>
>> package fr.iscpif.testscalascript
>>
>> import javax.script.ScriptContext
>> import javax.script.ScriptEngine
>> import javax.script.ScriptEngineManager
>> import javax.script.ScriptException
>> import javax.script.SimpleBindings
>> import org.apache.sling.scripting.scala.ScalaScriptEngineFactory
>> import scala.tools.nsc.Settings
>>
>> /**
>> * Hello world!
>> *
>> */
>> object App {
>>
>> def main(args: Array[String]) {
>> println("Hello World!")
>>
>> val mgr = new ScriptEngineManager
>> val engine = (new ScalaScriptEngineFactory).getScriptEngine
>> val settings = new scala.tools.nsc.Settings
>> settings.usejavacp.value = true
>>
>> engine.put(ScalaScriptEngineFactory.SCALA_SETTINGS, settings)
>>
>> val script = """
>> package script {
>> class Demo(args: DemoArgs) {
>> println("Hello from scala")
>> }
>> }
>> """
>> engine.getContext.setAttribute("scala.script.class", "script.Demo", ScriptContext.ENGINE_SCOPE)
>>
>> try {
>> engine.eval(script)
>> //" package script {object Test {def main(args: Array[String]) = {println(\"Hello, world from scala!\")}}}")
>> } catch {
>> case ex => ex.printStackTrace
>> }
>>
>> }
>> }
>
>
> Le mercredi 05 janvier 2011 à 17:54 +0100, Michael Dürig a écrit :
>> Romain,
>>
>> this is a class path issue: the Scala compiler doesn't find the Scala
>> library jar. There have been some changes between Scala 2.7 and 2.8:
>> AFAIK in 2.8 the environment class path (java.class.path) is not passed
>> to the compiler anymore.
>>
>> You should be able to work around this by passing the -usejavacp to the
>> Scala compiler explicitly. This can be done by adding a "scala.settings"
>> key with a value of type scala.tools.nsc.Settings to the ScriptContext.
>> See the sources for ScalaScriptEngine and ScalaScriptEngineFactory for
>> more details.
>>
>> Michael
>>
>> On 5.1.11 17:19, Romain wrote:
>>> Hi Michael,
>>>
>>> I am trying to use org.apache.sling.scripting.scala.script with jsr 223
>>> in a test project. But I get the following exception:
>>>
>>>> Exception in thread "main" scala.tools.nsc.MissingRequirementError: object scala not found.
>>>> at scala.tools.nsc.symtab.Definitions$definitions$.getModuleOrClass(Definitions.scala:517)
>>>> at scala.tools.nsc.symtab.Definitions$definitions$.ScalaPackage(Definitions.scala:37)
>>>> at scala.tools.nsc.symtab.Definitions$definitions$.ScalaPackageClass(Definitions.scala:38)
>>>> at scala.tools.nsc.symtab.Definitions$definitions$.UnitClass(Definitions.scala:83)
>>>> at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:789)
>>>> at scala.tools.nsc.Global$Run.(Global.scala:604)
>>>> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:126)
>>>> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:142)
>>>> at org.apache.sling.scripting.scala.interpreter.ScalaInterpreter.compile(ScalaInterpreter.scala:152)
>>>> at org.apache.sling.scripting.scala.ScalaScriptEngine$$anonfun$1.apply(ScalaScriptEngine.scala:113)
>>>> at org.apache.sling.scripting.scala.ScalaScriptEngine$$anonfun$1.apply(ScalaScriptEngine.scala:113)
>>>> at org.apache.sling.scripting.scala.ScalaScriptEngine.writeLocked(ScalaScriptEngine.scala:171)
>>>> at org.apache.sling.scripting.scala.ScalaScriptEngine.eval(ScalaScriptEngine.scala:112)
>>>> at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
>>>> at fr.iscpif.testscalascript.App.main(App.java:19)
>>>
>>> Do you have any idea why ?
>>>
>>> Cheers,
>>> Romain
>>>
>>> PS:
>>>
>>> My code is:
>>>
>>>> import javax.script.ScriptEngine;
>>>> import javax.script.ScriptEngineManager;
>>>> import javax.script.ScriptException;
>>>>
>>>> /**
>>>> * Hello world!
>>>> *
>>>> */
>>>> public class App {
>>>>
>>>> public static void main(String[] args) {
>>>> System.out.println("Hello World!");
>>>>
>>>> ScriptEngineManager mgr = new ScriptEngineManager();
>>>> ScriptEngine jsEngine = mgr.getEngineByName("scala");
>>>> try {
>>>> jsEngine.eval("println(\"Hello, world from scala!\")");
>>>> } catch (ScriptException ex) {
>>>> ex.printStackTrace();
>>>> }
>>>>
>>>> }
>>>> }
>>>
>>> And I build the application with the following maven script:
>>>
>>>> >>> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
>>>> 4.0.0
>>>>
>>>> fr.iscpif
>>>> testscalascript
>>>> 1.0-SNAPSHOT
>>>> jar
>>>>
>>>> testscalascript
>>>> http://maven.apache.org
>>>>
>>>>
>>>> UTF-8
>>>>
>>>>
>>>>
>>>>
>>>> org.apache.sling
>>>> org.apache.sling.scripting.scala.script
>>>> 0.9.0-SNAPSHOT
>>>>
>>>>
>>>> org.slf4j
>>>> slf4j-api
>>>> 1.6.1
>>>>
>>>>
>>>> org.scala-lang
>>>> scala-library
>>>> 2.8.1
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> maven.iscpif.fr
>>>> ISCPIF repository
>>>> http://maven.iscpif.fr/public-snapshots/
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>> Le lundi 06 septembre 2010 à 08:39 +0000, Michael a écrit :
>>>>> Why is it compatible only with
>>>>> scala 2.7? Will it be updated for the needs of the apache sling project?
>>>>> We would be very interesting having a library for that purpose, is there
>>>>> any plan for making this bunch of code a maintained library?
>>>>
>>>> It is Scala 2.7 only since no one came around updating it to Scala 2.8 yet. Also
>>>> there is some discussion on where this implementation should live [1, 2] since
>>>> Apache Sling is not the right place. And finally there is an issue on the Scala
>>>> bug tracker [3].
>>>> Updating this to Scala 2.8 is in the back of my head for some time. However it
>>>> seems I wont have enough time at the moment.
>>>>
>>>> Michael
>>>>
>>>> [1] http://markmail.org/thread/fpd3ukqm3dhghwwc
>>>> [2] http://markmail.org/thread/mp6scm4ga4g4jz3q
>>>> [3] https://lampsvn.epfl.ch/trac/scala/ticket/874
>>>>
>>>
>>>
>>
>
>

Daniel Dekany
Joined: 2011-01-06,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Scala interpreter classloader + OSGi

BTW, I wonder, what's here *intrinsic* problem that prevents the
compilers (like javac too, AFAIK) to use a ClassLoader directly (like
in this case the ClassLoader of the bundle) instead of a class-path?
Yes, a ClassLoader returns Class-es, not binaries, also they might
trigger static initializations (or resolve=false might prevents
that... whatever), but then, isn't ClassLoader.getResourceAsStream
good enough for getting the binaries? Can this situation ever be
fixed, even if on the Java platform level?

Michael
Joined: 2009-02-23,
User offline. Last seen 20 weeks 1 day ago.
Re: Re: Scala interpreter classloader + OSGi

Class loaders provide no means for traversal of the class space. This is
not and issue for javac AFAICT but it would be for scalac. Java
introduced the JavaFileManager interface [1] in 1.6 for that very purpose.

[1]
http://download.oracle.com/javase/6/docs/api/javax/tools/JavaFileManager...

On 6.1.11 15:01, Daniel Dekany wrote:
> BTW, I wonder, what's here *intrinsic* problem that prevents the
> compilers (like javac too, AFAIK) to use a ClassLoader directly (like
> in this case the ClassLoader of the bundle) instead of a class-path?
> Yes, a ClassLoader returns Class-es, not binaries, also they might
> trigger static initializations (or resolve=false might prevents
> that... whatever), but then, isn't ClassLoader.getResourceAsStream
> good enough for getting the binaries? Can this situation ever be
> fixed, even if on the Java platform level?
>

Daniel Dekany
Joined: 2011-01-06,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Scala interpreter classloader + OSGi

Thursday, January 6, 2011, 3:23:28 PM, Michael Dürig wrote:

> Class loaders provide no means for traversal of the class space. This is
> not and issue for javac AFAICT but it would be for scalac.

Indeed, importing implicit objects combined with import somepackage._
already makes traversing unavoidable... /-:

> Java introduced the JavaFileManager interface [1] in 1.6 for that
> very purpose.
>
> [1]
> http://download.oracle.com/javase/6/docs/api/javax/tools/JavaFileManager...
>
> On 6.1.11 15:01, Daniel Dekany wrote:
>> BTW, I wonder, what's here *intrinsic* problem that prevents the
>> compilers (like javac too, AFAIK) to use a ClassLoader directly (like
>> in this case the ClassLoader of the bundle) instead of a class-path?
>> Yes, a ClassLoader returns Class-es, not binaries, also they might
>> trigger static initializations (or resolve=false might prevents
>> that... whatever), but then, isn't ClassLoader.getResourceAsStream
>> good enough for getting the binaries? Can this situation ever be
>> fixed, even if on the Java platform level?

Daniel Dekany
Joined: 2011-01-06,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: Scala interpreter classloader + OSGi

Thursday, January 6, 2011, 5:09:20 PM, Daniel Dekany wrote:

> Thursday, January 6, 2011, 3:23:28 PM, Michael Dürig wrote:
>
>> Class loaders provide no means for traversal of the class space. This is
>> not and issue for javac AFAICT but it would be for scalac.
>
> Indeed, importing implicit objects combined with import somepackage._
> already makes traversing unavoidable... /-:

Except... implicit objects can't be top-level outside a package
object, and package objects has a class with a well-known name where
it could store the list of member class names.

Maybe it's simply that the trial-and-error that would be necessary to
find out from which "import somepackage._" a certain name comes from
is unacceptable. Then that's also an issue for javac.

>> Java introduced the JavaFileManager interface [1] in 1.6 for that
>> very purpose.
>>
>> [1]
>> http://download.oracle.com/javase/6/docs/api/javax/tools/JavaFileManager...
>>
>> On 6.1.11 15:01, Daniel Dekany wrote:
>>> BTW, I wonder, what's here *intrinsic* problem that prevents the
>>> compilers (like javac too, AFAIK) to use a ClassLoader directly (like
>>> in this case the ClassLoader of the bundle) instead of a class-path?
>>> Yes, a ClassLoader returns Class-es, not binaries, also they might
>>> trigger static initializations (or resolve=false might prevents
>>> that... whatever), but then, isn't ClassLoader.getResourceAsStream
>>> good enough for getting the binaries? Can this situation ever be
>>> fixed, even if on the Java platform level?
>

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland