2014-11-08 76 views
0

我正在使用JRuby從Java程序動態運行Ruby腳本。這些腳本使用ARGV和包含名爲「ctx」的附加信息的對象接收參數。然後,他們對這些信息執行一些操作,並將其結果返回給stdout,或者如果出現問題,則向stderr發送錯誤消息。這是我用來執行Ruby腳本代碼:JRuby:將stdout重定向到StringWriter會產生空輸出

String script = Joiner.on('\n').join(Files.readAllLines(Paths.get(path), StandardCharsets.UTF_8)); // read file from 
script = "require 'rubygems'\n" + script; // make gems work 

ScriptingContainer rb = new ScriptingContainer(LocalVariableBehavior.PERSISTENT); 
rb.setCompatVersion(CompatVersion.RUBY1_9); 

String cwd = Paths.get("").toAbsolutePath().toString(); 
rb.setCurrentDirectory(cwd); // set working directory of scripts to working directory of application 

StringWriter out = new StringWriter(); 
PrintWriter pwOut = new PrintWriter(out); 

StringWriter err = new StringWriter(); 
PrintWriter pwErr = new PrintWriter(err); 

String[] argsAry = args.split(" "); 

rb.setOutput(pwOut); 
rb.setError(pwErr); 
rb.setArgv(argsAry); // set output writer, error writer and argv 

rb.put("ctx", ctx); // add ctx to script container 

try { 
    rb.runScriptlet(script); 
} catch(Throwable t) { 
    logger.error("An exception occurred during JRuby execution! (ctx-id=" + 
      ctx.getId() + ")", t); 
} 

out.close(); 
err.close(); // close writers 

System.out.println(out.getBuffer()); // for debugging purposes 

System.err.println(err.getBuffer()); // print stderr result to stderr, 
return out.getBuffer().toString(); // and return stdout result 

這是我使用測試Ruby腳本:

text = ARGV * ' ' 

puts text 

現在我的問題是,這兩個緩衝區完全空在執行ruby腳本之後。我只是在stdout/err中得到兩個空行,並沒有返回任何結果。使用另一個腳本,我已確保腳本能夠運行並且ctx已成功傳遞到腳本。

事情我已經試過不已:

  • 內用CTX變量的結果傳遞到java程序,用rb.get進行檢索 - NullPointerException異常試圖訪問CTX
  • 內用CTX變量不使用rb.get - 變量是空
  • 設定在腳本中的字符串,將它傳遞給程序,使用rb.get - NPE試圖在人訪問字符串
  • 不使用緩衝區L - 沒有東西寫到標準輸出/犯錯
  • 只需使用StringWriters,而不是將它們與PrintWriters相結合的 - 沒有任何變化,但the answer to this question建議我做
  • 使用其他COMPAT版本初始化容器 - 沒有任何變化
  • 使用不同LocalVariableBehavior - 沒有變化
  • 使用rb.setWriter/rb.setErrorWriter,而不是rb.setOutput/rb.setError - 沒有變化

任何幫助,將不勝感激。

回答

0

經過一番實驗,我設法通過在構造函數中將LocalContextScope的rb設置爲THREADSAFE,並在執行後清空所有四個編寫器來解決此問題。