Rob,

Cool. I hope you can shed some light. Looking forward to it.

Thanks,

Matt

On Fri, Jan 1, 2010 at 9:10 PM, Rob Heittman <[email protected]> wrote:
> 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
>
>
>

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

    http://xircles.codehaus.org/manage_email


Reply via email to