I'm not in the right place to give a detailed answer today, but we
have JRuby working well under OSGi on iucnredlist.org, with the
interpreter exposed as a service ... I will drill into your example
more tomorrow and see if our approaches are applicable.  Might be.



On Jan 1, 2010, at 9:56 PM, Matt Stine <[email protected]> wrote:

> Hi, all. Charles Nutter requested via Twitter that I post up the
> issues I'm having getting JRuby to play nice in an OSGi environment.
>
> You can find all of the code in question at http://github.com/mstine/pgovm
> .
>
> Basically, my goal is to demonstrate the ability to implement OSGi
> services in alternative JVM languages without exposing the chosen
> implementation language to consumers of those services. I do this by
> providing a public API as a Java interface (see the pgo-vm-api
> module). This API provides all of the data types necessary to consume
> the service. I then implement the API in other bundles, and expose
> those implementations as services, witht the service interface being
> the Java interface from the public API. I've successfully done this so
> far in:
>
> - Java
> - Groovy
> - Scala
>
> This week I set out to do the same in JRuby. First off, kudos to the
> fact that the JRuby JARS available in the Codehaus Maven repo are
> proper OSGi bundles. As it turns out, its actually quite easy to
> execute some arbitrary Ruby code from within an OSGi bundle. All one
> needs to do is make sure that the JRuby 1.4.0 bundle is properly
> provisioned into the container and then use the new embeded script
> runner to fire it off. The first problem occurs when trying to
> implement the Java interface (or reference any Java code outside of
> the JRuby bundle for that matter). The classloader currently in scope
> cannot see the interface. The only workaround I've found so far that
> seems to get anywhere is to add a directive to the JRuby jar manifest:
>
> DynamicImport-Package: *
>
> This isn't entirely desirable, as in basically cracks open the entire
> world for JRuby to see. Any package that isn't explicitly imported by
> JRuby can now potentially be found by scanning all available bundles,
> and if found, access them. At this point, our first problem is solved.
> If I use pax-provision (part of Pax Construct, see
> http://wiki.ops4j.org/display/paxconstruct/Pax+Construct) to start up
> the OSGi container and provision JRuby, the API bundle, and the JRuby
> service implementation bundle, all seems to go well, as the service
> bundle is started and the service registered:
>
> osgi> ss
>
> Framework is launched.
>
> id      State       Bundle
> 0       ACTIVE      org.eclipse.osgi_3.5.1.R35x_v20090827
> 1       ACTIVE
> com.mattstine.polyglotosgi.vendingmachine.pgo-vm-jruby-
> impl_1.0.0.SNAPSHOT
> 2       ACTIVE
> com.mattstine.polyglotosgi.vendingmachine.pgo-vm-api_1.0.0.SNAPSHOT
> 3       ACTIVE      org.jruby.jruby_1.4.0
>
> osgi> bundle 1
> com.mattstine.polyglotosgi.vendingmachine.pgo-vm-jruby-
> impl_1.0.0.SNAPSHOT [1]
> Id=1, Status=ACTIVE      Data
> Root=/Users/mstine/Projects/polyglot-osgi-talk/code/pgovm/pgo-vm-
> jruby-impl/runner/equinox/org.eclipse.osgi/bundles/1/data
> Registered Services
>  {com.mattstine.polyglotosgi.vendingmachine.api.VendingMachine}=
> {service.id=26}
>
> You can see here that bundle 1 is the JRuby implementation bundle, and
> that it exposes a service via the API Java interface.
>
> On to the next issue....in-container testing. I have a set of tests
> for this API that all of the various implementations should pass.
> These are implemented via a JUnit 4 test case using Pax Exam, which is
> a support framework for testing OSGi bundles (see
> http://wiki.ops4j.org/display/paxexam/Pax+Exam). The pgo-vm-tests
> module in the GitHub project contains the test cases as well as the
> proper pom.xml for leveraging Pax Exam. Basically, Pax Exam starts up
> an OSGi container of choice, provisions your requested bundles, and
> then runs the unit tests against them. I've attempted this against the
> three major containers (Equinox, Felix, and Knopflerfish), and I get
> different results, both seeming related to classloading. On Equinox,
> here you can see an excerpt of the test bootstrapping:
>
> [        PaxRunnerTestContainer] - Test container (Pax Runner 0.17.2)
> started in 25545 millis
> STARTING com.mattstine.polyglotosgi.vendingmachine.jruby
> REGISTER
> com.mattstine.polyglotosgi.vendingmachine.jruby.internal.VendingMachineJRubyImpl


> [     RemoteBundleContextClient] - Remote bundle context found after
> 5887 millis
> VM IMPL = org.jruby.gen.interfaceimpl1814023...@19ed13da
> [        PaxRunnerTestContainer] - Shutting down the test container
> (Pax Runner)
>
> STOPPING
> com.mattstine.polyglotosgi.vendingmachine.jruby.internal.VendingMachineJRubyImpl


>
> [             DefaultJavaRunner] - Platform has been shutdown.
>
> What's important to note is that the test class is actually able to
> get an instance of the service, as evidenced by the println statement
> on the 5th line of output above. That println occurs in the setup
> method (annotated w/ @Before) in the test case. However, when we
> actually try to execute the first test method, things blow up, as
> below:
>
> ---
> ---
> ---
> ----------------------------------------------------------------------
> Test set:
> com.mattstine.polyglotosgi.vendingmachine.tests.jruby.VendingMachineJRubyTests


> ---
> ---
> ---
> ----------------------------------------------------------------------
> Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 32.766
> sec <<< FAILURE!
> testEmptyInventory
> [equinox]
> (com.mattstine.polyglotosgi.vendingmachine.tests.jruby.VendingMachineJRubyTests)
> Time elapsed: 32.706 sec  <<< ERROR!
> java.lang.NoClassDefFoundError: org/jruby/java/MiniJava
>      at org.jruby.gen.InterfaceImpl1814023411.showInventory(org/
> jruby/gen/InterfaceImpl1814023411.gen:5)
>      at
> com.mattstine.polyglotosgi.vendingmachine.tests.jruby.VendingMachineJRubyTests.testEmptyInventory(
> VendingMachineJRubyTests.java:37)
>      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>      at sun.reflect.NativeMethodAccessorImpl.invoke
> (NativeMethodAccessorImpl.java:39)
>      at sun.reflect.DelegatingMethodAccessorImpl.invoke
> (DelegatingMethodAccessorImpl.java:25)
>      at java.lang.reflect.Method.invoke(Method.java:597)
>      at
> org.ops4j.pax.exam.junit.extender.impl.internal.CallableTestMethodImpl.injectContextAndInvoke(
> CallableTestMethodImpl.java:128)
>      at
> org.ops4j.pax.exam.junit.extender.impl.internal.CallableTestMethodImpl.call(
> CallableTestMethodImpl.java:96)
>      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>      at sun.reflect.NativeMethodAccessorImpl.invoke
> (NativeMethodAccessorImpl.java:39)
>      at sun.reflect.DelegatingMethodAccessorImpl.invoke
> (DelegatingMethodAccessorImpl.java:25)
>      at java.lang.reflect.Method.invoke(Method.java:597)
>      at
> org.ops4j.pax.exam.rbc.internal.RemoteBundleContextImpl.remoteCall
> (RemoteBundleContextImpl.java:78)
>      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>      at sun.reflect.NativeMethodAccessorImpl.invoke
> (NativeMethodAccessorImpl.java:39)
>      at sun.reflect.DelegatingMethodAccessorImpl.invoke
> (DelegatingMethodAccessorImpl.java:25)
>      at java.lang.reflect.Method.invoke(Method.java:597)
>      at sun.rmi.server.UnicastServerRef.dispatch
> (UnicastServerRef.java:305)
>      at sun.rmi.transport.Transport$1.run(Transport.java:159)
>      at java.security.AccessController.doPrivileged(Native Method)
>      at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
>      at sun.rmi.transport.tcp.TCPTransport.handleMessages
> (TCPTransport.java:535)
>      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0
> (TCPTransport.java:790)
>      at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run
> (TCPTransport.java:649)
>      at java.util.concurrent.ThreadPoolExecutor$Worker.runTask
> (ThreadPoolExecutor.java:886)
>      at java.util.concurrent.ThreadPoolExecutor$Worker.run
> (ThreadPoolExecutor.java:908)
>      at java.lang.Thread.run(Thread.java:637)
> Caused by: java.lang.ClassNotFoundException: org.jruby.java.MiniJava
>      at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
>      at java.security.AccessController.doPrivileged(Native Method)
>      at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
>      at java.lang.ClassLoader.loadClass(ClassLoader.java:315)
>      at java.lang.ClassLoader.loadClass(ClassLoader.java:250)
>      at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:398)
>      ... 27 more
>
> On Felix (and very similar on Knopflerfish), we actually don't even
> get an instance of the service, as it blows up at startup:
>
> STARTING com.mattstine.polyglotosgi.vendingmachine.jruby
> REGISTER
> com.mattstine.polyglotosgi.vendingmachine.jruby.internal.VendingMachineJRubyImpl


> ERROR: Error starting
> file:/var/folders/4r/4r4zqex3Fs8-koSqNtfdvU+++TM/-Tmp-/
> paxexam_runner_mstine/bundles/
> com.mattstine.polyglotosgi.vendingmachine.pgo-vm-jruby-
> impl_1.0.0.SNAPSHOT.jar
> (org.osgi.framework.BundleException: Activator start error in bundle
> com.mattstine.polyglotosgi.vendingmachine.pgo-vm-jruby-impl [7].)
> :1: library `enumerator' could not be loaded:
> java.lang.ClassNotFoundException:
> org.jruby.libraries.EnumeratorLibrary (LoadError)
>      ...internal jruby stack elided...
>      from (unknown).(unknown)(:1)
> [     RemoteBundleContextClient] - Remote bundle context found after
> 3430 millis
> VM IMPL = null
> [        PaxRunnerTestContainer] - Shutting down the test container
> (Pax Runner)
>
>
> [             DefaultJavaRunner] - Platform has been shutdown.
>
> In both cases, it seems as if the classloader cannot see portions of
> JRuby. What's frustrating is that even if I bring in all of the JRuby
> packages via a Require-Bundle directive, I still get this behavior in
> all three containers.
>
> Any ideas? Any help would be greatly appreciated.
>
> Thanks!
>
>
>
>
> Matt Stine
> Java User Group Leader
>
> Memphis/Mid-South Java User Group
> Mail Stop 754
> 262 Danny Thomas Place
> Memphis, TN 38105 USA
> Phone: 901-214-JAVA
> Email: [email protected]
> http://www.linkedin.com/in/mattstine
> http://www.mattstine.com
>
>
> Want a signature like this?
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>    http://xircles.codehaus.org/manage_email
>
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to