Clojure vs OSGi once again...

1,191 views
Skip to first unread message

Mark Derricutt

unread,
Oct 13, 2013, 5:10:50 AM10/13/13
to clo...@googlegroups.com

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

Laurent PETIT

unread,
Oct 13, 2013, 6:30:29 AM10/13/13
to clo...@googlegroups.com
Hi Marc,

The clojure.osgi library aims at easing the pain in this area ( https://github.com/aav/clojure.osgi ). 

But to be honest I don't really know it's current status. 

For Counterclockwise, I've taken inspiration from clojure.osgi and integrated the core concepts into a few classes. 
In a nutshell, every entry point to the clojure world (especially for loading namespaces -potentially lazily thanks to eclipse lazy plugins infrastructure-) is wrapped in a call that ensures that as much dynamic bindings as possible are established, as well as the context class loader set.

You can see all this by looking at the activator for counterclockwise. 

HTH,

Laurent

Mark Derricutt

unread,
Oct 14, 2013, 3:29:21 AM10/14/13
to clo...@googlegroups.com

Cheers,

I took the time this morning to hack around a bit, and forked the repository and updated it to:

  • Use, and embed/re-export clojure 1.5.1, exporting clojure related packages.
  • Use the maven-bundle-plugin

From there I just adapted my internal packages to use it, and now have something up and running our OSGi/Karaf based application, now to actually get some real code written and we'll be well on our way to being free from the shackles of Java.

I'm thinking it may be a good idea to move the clojure-osgi project to it's own repository so that it can be released out the wild. Now that I've got things working, I can see I'll be adding some more support functions to handle configuration admin queries etc.

Mark

signature.asc

Evile Cruela

unread,
Feb 4, 2016, 3:09:40 PM2/4/16
to Clojure
Is there a complete example of a bundle activator in clojure that you could point me to please. I have written them in java and I'd like to try it in clojure.

Thanks

Mark Derricutt

unread,
Feb 4, 2016, 6:37:23 PM2/4/16
to Clojure
On 5 Feb 2016, at 9:07, Evile Cruela wrote:

> Is there a complete example of a bundle activator in clojure that you could point me to please. I have written them in java and I'd like to try it in clojure.

Thanks for reminding me I should update the clojure-osgi build for Clojure 1.8.

A complete example can be found in my https://github.com/talios/clojure.osgi.demo repo.

Mark


--
Mark Derricutt
http://www.theoryinpractice.net
http://www.chaliceofblood.net
http://plus.google.com/+MarkDerricutt
http://twitter.com/talios
http://facebook.com/mderricutt
signature.asc

Mark Derricutt

unread,
Feb 4, 2016, 6:44:45 PM2/4/16
to Clojure

On 5 Feb 2016, at 9:07, Evile Cruela wrote:

Is there a complete example of a bundle activator in clojure that you could point me to please. I have written them in java and I'd like to try it in clojure.

<dependency>
  <groupId>com.theoryinpractise</groupId>
  <artifactId>clojure.osgi</artifactId>
  <version>1.8.0-1</version>
</dependency>

Should be winging it's way to Maven Central in an hour or so on the next sync cycle.

signature.asc
Reply all
Reply to author
Forward
0 new messages