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
