Hey all, Once again I'm lending my hand at trying to get some clojure code working under OSGi, and once again hitting issues with the good ole class loader. I have a simple OSGi bundle project which embeds clojure.jar, and contains a single source file:
(ns com.theoryinpractise.activator.osgi.components
(:import (org.osgi.framework BundleActivator)))
(deftype MyActivator []
BundleActivator
(start [this context]
(println "Hello from service"))
(stop [this context]
(println "stopping")))
In my OSGi metadata I have
`com.theoryinpractise.activator.osgi.components.MyActivator` listed as the
`Bundle-Activator` for the bundle, and when I load it I get the following
exception:
Caused by: java.lang.ExceptionInInitializerError
at
com.theoryinpractise.activator.osgi.components.MyActivator.<clinit>(components.clj:4)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at java.lang.Class.newInstance(Class.java:374)
at
org.apache.felix.framework.Felix.createBundleActivator(Felix.java:4336)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:2141)
... 32 more
Caused by: java.io.FileNotFoundException: Could not locate
clojure/core__init.class or clojure/core.clj on classpath:
at clojure.lang.RT.load(RT.java:443)
at clojure.lang.RT.load(RT.java:411)
at clojure.lang.RT.doInit(RT.java:447)
at clojure.lang.RT.<clinit>(RT.java:329)
... 40 more
java.lang.ExceptionInInitializerError
When I look at the decompiled class ( using JD-GUI ) I see there's a static
initialiser pulling in the `println` function:
public final class MyActivator implements BundleActivator, IType {
public static final Var const__0 = (Var)RT.var("clojure.core", "println");
…
Tracing this down into `RT.baseLoader()`:
static public ClassLoader baseLoader(){
if(Compiler.LOADER.isBound())
return (ClassLoader) Compiler.LOADER.deref();
else if(booleanCast(USE_CONTEXT_CLASSLOADER.deref()))
return Thread.currentThread().getContextClassLoader();
return Compiler.class.getClassLoader();
}
I find that `Compiler.LOADER.isBound()` is false, and
`booleanCast(USE_CONTEXT_CLASSLOADER.deref())` is true, which leads to using
the class loader for the OSGi runtime and *not* the class loader that happens
to actually know anything about Clojure, which would be the OSGi Bundle
classloader for my package.
Does anyone know of a way around this? Or will I need to give up on trying to
use pure-clojure here and use Java for my activator, and call
`Compiler.LOADER.set(myclassloader)` and then do some `RT.*` love?
Cheers,
Mark
signature.asc
Description: OpenPGP digital signature
