javajrubyjruby-java-interop

JRuby file not run when executing from jar file (was: System.out.println not working from jar file)


(Crossposted at JRuby Forum, but posted here again because I did not get any answer yet).

Platform: jruby 9.0.4.0 (2.2.2) 2015-11-12 b9fb7aa Java HotSpot(TM) 64-Bit Server VM 24.79-b02 on 1.7.0_79-b15 +jit [Windows 7-amd64]

Main program in Java, calling JRuby code via RedBridge Core. Java classes are in a Jar-File.

This setup works, as long I don't insist that the Ruby code is also executed from within the Jar-File, instead of being searched inside the file system. If I run the code from a Jar-File, the JRuby stdout seems to have disappeared.

First, here is the WORKING case:

// My main program (Jmain.java):
import vp.VP;
public class Jmain {
  public static void main(String[] args){
    System.out.println("Jmain started");
    VP vp = new vp.VP();
    System.out.println("vp instance created");
    vp.run();
    System.out.println("Jmain terminating");
  }
}

// My VP class (VP.java):
package vp;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.RubyObject; 
import org.jruby.embed.ScriptingContainer;
import org.jruby.embed.LocalContextScope;
import java.util.*;
public class VP {
  private ScriptingContainer container;
  public VP() {
    container = new ScriptingContainer(LocalContextScope.SINGLETHREAD);
  }
  public void run() {
    RubyObject asahi =
        (RubyObject)container.runScriptlet( 
            org.jruby.embed.PathType.RELATIVE,"rbsrc/bridge.rb");
    System.out.println("scriptlet executed");
  }
}

# My Ruby program rbsrc/bridge.rb
puts "Entering bridge" # Just to see what's going on
File.write("out.txt","This file was created by bridge.rb\n")
# ... rest of the code not shown

:: I put everything into a jar file, including the Ruby files
:: (although I don't need them there yet).
jar cvfm jars\vp.jar .... rbsrc

:: The program is executed like this:
java -cp c:\jruby-9.0.4.0\lib\jruby.jar;jars\vp.jar Jmain

I see the result of all the println statements, and the file out.txt is created.

Now for the NON-WORKING case:

In the whole setting, I change ONLY ONE line: The invocation of bridge.rb becomes

RubyObject asahi = 
    (RubyObject)container.runScriptlet(
         org.jruby.embed.PathType.CLASSPATH,"bridge.rb");

That is, I replace RELATIVE by CLASSPATH, and drop the "rbsrc/". When I run this, I get no error message, I get the output of all the println statements, BUT I don't see the output of the 'puts' statement, nor is the file out.txt created!

Note that bridge.rb seems to be loaded correctly (if I change bridge.rb to a different name, I get an exception), but it doesn't seem to be executed.

How come?

UPDATE: My problem description was wrong! There is nothing wrong with stdout, but it seems that my JRuby code bridge.rb is not executed! runScriptlet returns null, and when I create a file inside the Ruby program, there is no file afterwards.

What am I doing wrong? I have all my JRuby files in one directory. I put them into my Jar file. I run it using jar -cp JARFILE MAINCLASS. What else is missing?

BTW, the whole example application can be found here. There is a readme.txt included.


Solution

  • You said

    I replace RELATIVE by CLASSPATH

    You probably changed the setting where java should search for classes from a relative path to the CLASSPATH.

    You probably have not set the correct CLASSPATH variable value for your jar files - meaning the place where java should check for extra classes (more).

    Try

    set classpath = .;yourFilename.jar;
    

    Notice that the dot (.) stands for the current directory.

    You can then attempt to execute it using the -jar parameter in your command prompt:

    java -jar yourFilename.jar
    

    If you don't have a manifest in your jar, attempt executing it using the -cp (or -classpath, which is identical) parameter to specify your class path implicitly.

    java -cp foo.jar full.package.name.MyClassName
    

    Now, as a second thought, I would check that the executing directory has the permissions for the jar execution and the file creation (write), just in case.

    UPDATE: It seems out by what you describe, that the problem is finally not in the classpath - as you don't have any exceptions, but in the path you have set for the file.

    I suggest that you check the relative path you have set for the file inside your application that has a correct reference (just the file name is not enough, as "rbsrc/bridge.rb" is a relative path inside the application folders and this should be kept even when changed the option from RELATIVE to CLASSPATH). The relative path is based on the application folder as root in that case.