- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Scala intepreter classloader + OSGi
Sun, 2010-09-05, 10:29
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
Sun, 2010-09-05, 15:47
#2
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
Sun, 2010-09-05, 18:27
#3
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
>
Sun, 2010-09-05, 18:47
#4
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.
Sun, 2010-09-05, 19:07
#5
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.
>
Sun, 2010-09-05, 20:37
#6
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
Sun, 2010-09-05, 21:17
#7
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
>
Sun, 2010-09-05, 22:57
#8
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
Mon, 2010-09-06, 07:27
#9
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
>
Mon, 2010-09-06, 09:47
#10
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
Wed, 2011-01-05, 17:27
#11
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
>
Wed, 2011-01-05, 17:57
#12
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
>>
>
>
Wed, 2011-01-05, 19:37
#13
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
> >>
> >
> >
>
Thu, 2011-01-06, 09:47
#14
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
>>>>
>>>
>>>
>>
>
>
Thu, 2011-01-06, 15:07
#15
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?
Thu, 2011-01-06, 15:27
#16
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?
>
Thu, 2011-01-06, 17:17
#17
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?
Thu, 2011-01-06, 17:37
#18
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?
>
> 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/