Using JRuby for rules

It seems python is the most popular programming language among OH-users, and I have read several who use Jython to write rules. However, being more of a rubyist myself, I thought I’d try to see if I can use JRuby the same way. I used the instructions for installing Jython, but substituted it for the Jruby .jar-file. When I restarted OH i got a log entry

2017-11-19 21:06:06.482 [INFO ] [.internal.GenericScriptEngineFactory] - Activated scripting support for ruby
2017-11-19 21:06:06.484 [DEBUG] [.internal.GenericScriptEngineFactory] - Activated scripting support with engine JSR 223 JRuby Engine(9.1.13.0) for ruby(jruby 9.1.13.0) with mimetypes [application/x-ruby] and file extensions [rb]

If I create a .rb-file in the automation/jsr223-folder the logs says:

2017-11-19 21:30:01.662 [DEBUG] [rt.internal.loader.ScriptFileWatcher] - in queue: {}
2017-11-19 21:30:01.672 [INFO ] [rt.internal.loader.ScriptFileWatcher] - Loading script 'testrule.rb'
2017-11-19 21:30:02.000 [DEBUG] [rt.internal.loader.ScriptFileWatcher] - Script loaded: testrule.rb
2017-11-19 21:30:02.003 [DEBUG] [rt.internal.loader.ScriptFileWatcher] - in queue: {}
2017-11-19 21:30:02.018 [INFO ] [rt.internal.loader.ScriptFileWatcher] - Loading script 'testrule.rb'
2017-11-19 21:30:02.147 [DEBUG] [rt.internal.loader.ScriptFileWatcher] - Script loaded: testrule.rb

But I can’t make the scripts do anything. If I just make a simple script like the Jython example in the docs (http://docs.openhab.org/configuration/jsr223-jython.html)

include_class org.slf4j.LoggerFactory

logger = LoggerFactory.getLogger("org.eclipse.smarthome.automation.examples")
logger.info("Test")

Nothing happens. And if I try to use

scriptExtension.importPreset("RuleSimple")
scriptExtension.importPreset("RuleSupport")

I just get an error in the logs

2017-11-19 21:51:32.967 [DEBUG] [rt.internal.loader.ScriptFileWatcher] - in queue: {}
2017-11-19 21:51:32.987 [INFO ] [rt.internal.loader.ScriptFileWatcher] - Loading script 'testrule.rb'
2017-11-19 21:51:33.044 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab2/automation/jsr223/testrule.rb': org.jruby.embed.EvalFailedException: (NameError) undefined local variable or method `scriptExtension' for main:Object
2017-11-19 21:51:33.046 [DEBUG] [rt.internal.loader.ScriptFileWatcher] - Script loaded: testrule.rb

Which at least means that the file gets loaded and parsed by JRuby. But it seems that the ESH/OH scope doesn’t get extended to JRuby.

I’m currently running OH 2.1.0 stable, would moving to a snapshot build solve anything? (Has any changes been made to the jsr223 implementation that could make it work better?)
Is it possible to work around this by for example make my own instance of whatever class scriptExtension is an instance of?
Is this something that has to be added explicitly for each scripting language in ESH? If that’s the case it’s probably too big of an undertaking for me as I’m not very familiar with java development.

I know I’m pretty much on my own here because not many users are interested in getting this to work besides me, but any pointers in the right direction would be much appreciated.

1 Like

My understanding is there is a whole lot of work that needs to be done to provide a layer between your language and OH and that just installing and activating the language is not sufficient. I would recommend looking at the code written to bridge between Jython, JavaScript, or Groovy (@Spaceman_Spiff or @steve1, can you point Anders in the right direction?) to see what sort of code would need to be implemented to connect up JRuby with OH. I’m pretty sure it is hosted on the ESH repos.

I think that is part of it for sure.

I think so.

I don’t think the work is done in Java but in the scripting language being added. I’m not fully up on how it all works though so can’t say for sure. I do think that Ruby would be an excellent addition to the available languages.

There are several considerations. First, various languages have varying support for the JSR223 API (some capabilities are optional). The languages also have varying degrees of integration with Java. Jython, Groovy and Nashorn Javascript seem to be the best in that regard.

That said, you generally should be able to run a script in just about any JSR223 language. The core API is not language-specific. However, many of the languages do not support subclassing Java classes so you wouldn’t be able to define rules with them.

I’ve tried JRuby, LuaJ and ABCL (Armed Bear Common LISP) and ran into different issues with each of them. The specific issue you are seeing is a strange one. I’d expect JRuby to at least be able to access the JSR223 scope and see the scriptExtensions object. To debug it, someone will need to use the Eclipse IDE with a debugger and step through the JSR223 call into JRuby to determine the scope issue with the JRuby implementation. This doesn’t look like a JSR223 API or an ESH issue from I’m seeing so far.

1 Like

Thank you both for your help.

Subclassing should be possible according to the JRuby wiki (https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby#integrating-jruby-and-java-classes-and-interfaces) so that wouldn’t (in theory) be a problem. As for the scope issue, I’ll try to see if I can get the IDE running and debug it, but I’m not sure my skills are enough for that…

Thank you again!

There were changes in the naming of scriptExtension, I don’t know if that build has that naming already.

Could you recheck with Openhab 2.2.0?

I have updated to 2.2 stable, but still the same problems.

2018-01-01 13:41:21.483 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab2/automation/jsr223/testrule.rb': org.jruby.embed.EvalFailedException: (NameError) undefined local variable or method `scriptExtension' for main:Object

I think that somehow JRuby don’t get access to the openhab packages or something. If I just make a simple rule with a logging statement:

org.slf4j.LoggerFactory.getLogger("org.eclipse.smarthome.automation.examples").info("Hello world!")

or try to import the slf4j classes i get the error

2018-01-01 13:36:51.845 [ERROR] [ipt.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab2/automation/jsr223/testrule.rb': org.jruby.embed.EvalFailedException: (NameError) missing class name (`org.slf4j.LoggerFactory')

If I add the line

require '/usr/share/openhab2/runtime/system/org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7.jar'

the error message disappears, because JRuby can access the class, but the logging statement doesn’t write to the openhab log.

Do you have any idea if it’s a limitaion in JRuby, or if I may have configured it wrong?

I don’t. I experimented with JRuby with JSR223 and OH1 and it (JRuby) didn’t work. To track this down, you’ll probably need to set up an Eclipse development environment for the SmartHome code, get the source code to JRuby and then step through in a debugger to determine the source of the problem. That’s the technique I was using to test various JSR223 implementations for OH1. JRuby has had numerous releases since I was experimenting so I don’t think my notes will help much at this point.

1 Like

Ok, seems like I have quite a bit of reading to do about debuggers, but I’ll see if I can get the time. Thanks for all your help!