Question

I want to create an simple osgi bundle to run ruby source file , so i using jruby-complete .Here is code example

A bundle which run jruby file

package activator;
import org.jruby.embed.ScriptingContainer;

public class Main {
    public void runRubySource(String[] args) {
        try {
            System.out.println("JRUBYYYYYYYYYYYYYYYYYYYYYYYYy");
            ScriptingContainer container = new ScriptingContainer();
            container.setArgv(args);
            container.runScriptlet("require 'ruby/test.rb'");
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }

    }
}

A bundle which using above bundle

package activator;
import activator.Main;
import org.jruby.embed.ScriptingContainer;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Test implements Activator{

    @Override
    public void start(BundleContext context) throws Exception {
        // TODO Auto-generated method stub
        Main m = new Main();
        String[] args = {"-c","C:\\fileconfig.conf"};
        m.runRubySource(args );

    }
    @Override
    public void stop(BundleContext context) throws Exception {
        // TODO Auto-generated method stub

    }
}

POM file for osgi bundle build using maven

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.insight</groupId>
    <artifactId>jruby</artifactId>
    <packaging>bundle</packaging>
    <name>JrubyDemo</name>
    <version>1.0</version>
    <dependencies>
        <dependency>
            <groupId>org.jruby</groupId>
            <artifactId>jruby-complete</artifactId>
            <version>1.7.10</version>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>4.3.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <version>2.0.1</version>
                <extensions>true</extensions>
                <configuration>
                    <Embed-Transitive>true</Embed-Transitive>
                    <Export-Package>*</Export-Package>
                    <instructions>
                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Steps :

Certainly, jruby/jruby.rb is contained in jruby-complete.jar ,not in my example bundle

So, what i have to do ??

Was it helpful?

Solution

(LoadError) no such file to load -- jruby/jruby.rb

I think you bundle is probably corrupt. BTW, jruby-complete is already an OSGI bundle, so try the same without wrapping: it should definitely be able to load its own classes.

However, for the next step:

container.runScriptlet("require 'ruby/test.rb'");

You're asking a class in the jruby bundle to load the resource from another bundle. The problem is that jruby-complete does not know about your bundle, as it's not wired to it via normal OSGI mechanims.

So you need some form of reverse-lookup mechanism to which lets the Jruby bundle locate resources/class in other bundles, without adding a direct dependency (RequireBundle or ImportPackage) to Jruby's bundle (as that would not be scalable if you want then to be able load from other bundles, or maybe reuse jruby in other contexts).

I'm using Eclipse Equinox for a similar setup, so I'm "spoiled" with nasty treats like Buddy Policy. Apart from being specific to that container has its own disadvantages, but it's been good enough for me.

Currently one generic OSGI 'equivalent' for BuddyPolicy=Global seems to be DynamicImport-Package, however it's only there as a last resort as less flexible than the above.

Both of the above involve adding a line into Jruby bundle's Manifest (again jruby-complete.jar but I happen to repackage the whole thing as org.jruby).

A better solution is probably JRuby's own OSGiScriptingContainer, where you can pass the loading bundle into your class, something like this:

package activator;
import org.jruby.embed.OSGIScriptingContainer;

public class Main {
    public void runRubySource(String[] args) {
        try {
            System.out.println("JRUBYYYYYYYYYYYYYYYYYYYYYYYYy");
            ScriptingContainer container = new OSGIScriptingContainer(Activator.getBundle());  // 
            container.setArgv(args);
            container.runScriptlet("require 'ruby/test.rb'");
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }    
    }
}

I haven't tried this but I'm going to change my setup as this is seems the right way.

OTHER TIPS

Scripting in general is a little different in OSGI, since scripting can be/is runtime and OSGI wants you to specify things at build-time (pulled this from the linked thread). For scripting using JRuby, you might be better off using JSR-223 to load your engine, as there has been work getting these two slightly incompatible techniques to work together.

Here is a similar thread talking about working with JSR-223 in OSGI with some solutions:

Is OSGi fundamentally incompatible with JSR-223 Scripting Language Discovery?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top