Writing rules in Java language? (Java as JSR223 language)

As OpenHAB is written in Java it would make perfect sense to use Java itself as scripting language. JShell along with some glue code should work. There is already a project that could be used to integrate it as a standard JSR223 language: GitHub - eobermuhlner/jshell-scriptengine: JShell script engine for Java (JSR-223 compatible)

What is necessary to configure OpenHAB for this usage?

2 Likes

We could call that “DSL rules”. What would be the advantage, from the user viewpoint?

I do not have an answer in terms of deep integration with OpenHab (vs going through the REST API).

However, in terms of the true meaning of scripting languages, Java is still not quite there yet. While newer versions of Java (up to 16) has been constantly improving the language syntax and the Stream API in Java 8 was really nice, it is still a long way from a streamlined scripting language like Python or Ruby. It is still too verbose.

It is however a legitimate option to write rules in. The advantages are the familiar programming language for some developers, and the same loading/unload mechanism similar to existing scripting engines.

The answer is simple: Everyone capable of writing Java code does not need to learn a new language to write script code for OpenHAB.

I wrote some scripts for my OpenHAB3 installation using ECMAScript as scripting language, but it still feels artifical as it at the end calls Java code all the time. So why not directly workin with Java instead of “wrapping” everything in Python, JavaScript or other scripting languages?

It is easy for me to read the JavaDoc to understand what OpenHAB classes like ItemRegistry do and how to use it. But it’s hard to use it in another language like JavaScript that is not my primary programming language (which is Java).

With the JSR233 scripting it should be possible to use “native Java” code for such scripts.

So my questions is mainly: What is necessary to create a new add-on like org.openhab.automation.groovyscripting and integrate it in an existing OpenHAB3 installation? What config is necessary? Where to put the bundle jar? Is there any doc about creating a new JSR223 based scripting language?

1 Like

I’m working on on addon for writing rules in java. I was hoping to publish something last week but basically got delayed. I have been working on the UniFi Protect binding instead.
I would expect to be able to publish something in the coming weeks. I have created an addon which listens to eventbus. To write rules you use annotations. All items are generated from the items files.

Big advantage for me writing rules in java is:

  • The IDE (Eclipse or intellij for true auto complete, and in time verification of code, items etc)
  • Able to debug, write unittests
  • Leverage full java API and libraries
  • Write common libraries and share code
  • Exception handling and more.

Since I like a lot of other people here got full time job, small kids and other addons to maintain it might take a while before I publish something. I aim to deliver something and then count on other to contribute, we will see how it goes.

Best Regards, S

4 Likes

I started experimenting with creating a new custom bundle:

Currently I’m stuck with a missing dependency:

Unresolved requirement: Import-Package: jdk.jshell

How do I add the reference to the standard JDK Shell package?

I would suggest to check these 2 threads:

It works fine for me.

While I agree that Java isn’t the most suited for scripting, I think having Java as an option for writing rules would not be bad. I would hope that any approach would try to retain enough of “how we do it now” to make it easier for users to transition between the various languages. The Helper Libraries, particularly those for Jython are a great example of this. It’s very easy, as a Rules DSL user, to see that parts of a Rules DSL rule reflected in the Python.

This is probably less of an issue for Java since you wouldn’t be tempted to hide the Java from itself as some of the other languages support is tempted to do.

One big problem I have in my ignorance on how all of this works would be how libraries would work. So my recommendations would be:

  • @michael-schnell and @Seaside, please work together
  • please try to structure the way users write rules to “look” enough like Rules DSL as much as is feasible to lower how much users need to relearn in order to migrate off of Rules DSL and or apply Rules DSL examples to Java
  • make sure libraries are supported, both the ability for users to include their own libraries and the ability to include third party libraries.

I’m happy to see so many working on new language support but not so happy seeing the various languages diverge too widely. It makes it harder for people to migrate, harder to document, and harder for some of the “power users” on the forum to support.

1 Like

Hey there, just want to add my 2 cents:
I was in the exact same situation a couple of month ago (strong java background, sick of the DSL rules due to lack of IDE support if you’re used to the real thing, …)
What I tried back then was to get to run the OH script engine with the Kotlin JSR223 engine. I came really close, some primitive test script loaded, but there were some class loading issues down in the depth of the the Kotlin JSR233 engine which prevented more complex scenarios.
Bottom line: Its all there to load any JSR233 compatible language. There might be some OH core tweaks necessary but there won’t be any documentation.
(you obviously already got familiar with the code in the automation package of the core.

I ended up using Groovy rules but have the feeling I am one of about 3 people doing that.

I don’t think it’s worth it to get the Java JSR233 flavour to run:

  • either just use Groovy, its almost the same
  • stick to the DSL rules (well… you don’t want that)
  • use the REST API (I was about to start that but… what the hell is OH good for when I do the real home automation stuff in my own application? If it’s not capable of doing it, we should get it that far…)
  • use the message broker options (e. g. MQTT) to connect your own app (same as with REST API applies here)

Why am I saying that? There are some drawbacks you should be aware of:
JSR233 is … well… special. Each script is loaded kind of independent of all others, so you can’t reuse stuff from other scripts. Refer to Groovy scripts: how to import another groovy file? - #3 by pravussum
I guess the solution would be the helper lib @rlkoshak mentioned, which ideally would have the same API for all supported languages (and needs to be implemented - it could probably be reused for Groovy/Kotlin/Java).

Another possibility would be a kind of “wrapper” addon which offers a “proprietary” API but - although being the most convenient solution for Java devs - it would be not optimal due to a couple of reasons

  • architecture-wise (REST API vs. OH core “half official” API vs. a new “bastard” API)
  • the OH core API is not meant to be exposed and not “stable” in a contract sense
  • it would diverge from the other APIs as @rlkoshak mentioned

Hope that was not too confusing :sunglasses:

If you write some tutorials, post some examples and help others on the forum, more will use it. There must be at least one or two Groovy users among the maintainers since it’s kept up to date and in fact was the first language to get a plugin in OH 3.

You may misunderstand what the Helper Librarys does and what it’s for. The Helper Libraries are a series of libraries to import into your scripts to make the creation of rules and other interactions with openHAB closer to what Rules DSL provides. For Python, for example, instead of defining a class and registering that with the rules registry, the HL provide some annotations so all you can write a rule that looks very similar to a Rules DSL rule.

But each language has it’s own set of libraries. You can’t use a Python annotation in a JavaScript rule.

But as much as is possible, the way the libraries work for each of the languages is similar. They help you write rules more like one does in Rules DSL (without the limitations) rather than taking a green field approach and making the experience in each language unique.

OK, API was maybe really inappropriate, “facade” might be better. I actually didn’t find it too hard to use the core classes directly, but what really was a problem with the scripts (and DSL rules are in the end just one of the supported script languages) is that you can’t reuse code from another script, thus the need for some kind of library.

If you import code from somewhere else, that somewhere else is by definition a library. You can’t import a script. If you have such code, there is a place to put it in the automation folder.

In Python you can put your personal library in automation/lib/python. It’s also possible, if a little awkward, to use pip to install third party libraries there.

In JavaScript you can put your personal library in automation/lib/javascript. You can even use those in rules defined through the UI, see OH 3 Examples: Writing and using JavaScript Libraries in MainUI created Rules. The nature of Nashorn and how openHAB uses it makes using third party libraries not quite so easy but still possible in some cases.

The jRuby Helper Libraries (no relation to the Jython/JavaScript libraries) are even available and installed using ruby gems.

The Helper Libraries wouldn’t be a thing if this sort of import were not possible. I don’t know how Groovy works but if there is a limitation on being able to import from the automation/lib/groovy library then that’s a limitation of that language, not a limitation of JSR223 languages in general.

In the last year or so (on and off, as many of us), I wrote some rules in JSR223 Python / Jython and created something you might call a library for use in Jython. While I like the ease of creating “short” rules in Jython (using the helper libraries), I strongly think of migrating away my library into a pure Java addon.

My point being: it heavily depends on what you want to do.

As @pravussum stated, JSR223 is “special”. Rules (or rather scripts) should have no interaction (due to the “isolated” loading of them). This isolation is not 100% - which I tried to (mis)use… but I would call it a fail :slight_smile: I have to restart OH every month due to mem leaks via orphaned items in Jython.

But I love :+1: Jython for things like input conversion, updating stats based on inputs, do some short calculation. The helper libraries and @rlkoshak 's openhab-rules-tools provide nice support for stuff like that…

@Seaside are you able to share any code or anything of what you’ve written so far? I’ve been trying to dig into how to consume SSE in Java and I must be looking in the wrong places because I’m not finding what I need. If you don’t mind sharing code showing how you were accomplishing it that might be helpful.

Thanks

Hi!

Yes I’ve been stuck at some class loading issues when compiling the rules in runtime, but it’s now solved. I have a very basic framework, that seem to work. I will spend time on cleaning the code up and moving it to automation (now resides under bindings). There are still things to add, for instance I only support a few types of items.

I’ll share a private repo with you once I’m done doing some more simple cleanup and basic documentation and we can see you think it’s a reasonable approach.

Br S

1 Like

Sounds great!

@mladams922 Pm your github username and I’ll share the private repo I’m working on.
It is working right now for some items, but far from done. See JRule Java Rules in OpenHAB 3 (Preview) (alpha)

I have opened up the repository and added some documentation now.

Thanks for posting, just let me add my 2 cents:
Your implementation is done as a binding, which does not really fit into the openHAB eco-system, it should be an automation package.
Second, you are forcing users to define items in files, what about GUI only users like me.
You really should support both sides…

Hi!

Please post in the other thread: JRule Java Rules in OpenHAB 3 (alpha)
If you have feedback to the binding, it’s good to have it in one place.

I agree, there are some benefits of having it as a binding (like exposing channels with information related to the rule engine, statistics and so on), but in the end I could not
see any easy way to add it as automation, there is no good base class to extend (at least that I could find), and there is very little documentation about this. The other jsr233 addons extends the JSRBase class, but this will not work for this binding. I will investigate if I can convert it to an automation package, but this is at least a start.

Although I have not tested the GUI created items, I believe it will work in its current state with GUI defined items. The binding connects to the eventbus and uses Itemregistry to fetch all items. I should support both sides yes, but I have limited time so I appreciate all feedback and help I can get.

BR S