openHAB 4.0 Milestone discussion

It depends. There’s a simple import you can do to make Nashorn JS work with GraalVM JS. So at worst it would be the addition of one line at the top

if(typeof(require) === "function") Object.assign(this, require('@runtime'));

That imports all the stuff that is available to Nashorn rules by default into a GraalVM JS. Note that there are some collisions in names (e.g. items is a reference to a Map of Item names and their current state in Nashorn but in GraalVM items is your interface to access, create, and remove Items. Therefore it’s better to assign @runtime to a variable but that means everywhere you use something injected into the rule (e.g. events.sendCommand()) you’ll have to prepend the variable. If you are going to go through that effort, you may as well port to GraalJS.

There are reference docs for building rules (and transformations) in GraalVM JS (note Nashorn provides ECMAScript 5.1 which was released almost a dozen years ago and has received no updates to the language since where as GraalVM JS provides ECMAScript 2021).

Unlike with Nashorn, GraalJS comes with the Helper Library (no need to clone a github repo and put it in the right spot) or it can be installed via npm. Also unlike Nashorn, the Helper Library goes to great lengths to provide a pure JavaScript interface to OH (all interactions with OH in Nashorn are through Java Classes and Objects) freeing you from needing to worry about type conversions in most cases.

The docs for GraalVM JS are very thorough and complete and can be found at JavaScript Scripting - Automation | openHAB. But because the Helper Library is so much more complete and comprehensive, porting to it is likely going to largely be a rewrite of most lines of a Nashorn rule. Though in my experience the GraalVM JS version of the code is roughly half the size of the Nashorn equivalent thanks to stuff that used to need to be imported (e.g. access to metadata) that come with the library now and new features added to ECMAScript in the dozen years since Nashorn.

To my knowledge there is no work being done in Nashorn now and none planned for the future. All new JS work is being done on GraalVM JS. The Nashorn add-on is there for backwards compatibility. Note: both Nashorn and GraalVM JS can be installed and used at the same time.

3 Likes

OK, sounds like GraalJS is the way to go then. With the Nashorn addon installed, how do you tell the system which JS your .js script is meant to be? Can you switch back and forth as you debug the migrated rules?

For UI rules they each use a different mime type.

In OH 3.4:

  • Nashorn: application/javascript
  • GraalVM JS: application/javascript;version=ECMAScript-2021

In OH 4:

  • Nashorn : application/javascript;version=ECMAScript-5.1 (I think)
  • GraalVM JS: application/javascript

In file based rules, Nashorn rules go under $OH_CONF/automation/jsr223/js (or something like that, I don’t really remember but if you are using Nashorn you already know) and GraalVM JS the files go under $OH_CONF/automaion/js.

While a Nashorn rule can be run on GraalVM, the opposite is not necessarily true. If you use the GraalVM JS Helper Library your rule or anything added to the language since 2011 your code will not run on Nashorn. So you will be talking about having two instances of a given rule with one enabled and the other disabled.

I believe this works for both file based and UI based rules and survives a reboot, but you should verify.

In MainUI you can disable/enable rules by clicking the pause icon at the top. So you can enable one and disable the other. Do your work and if it’s not ready for prime time disable the new and enable the old until the new rule is ready to take over.

If that doesn’t work for file based rules, you’ll have to use something like changing the extension of the files or commenting out to switch between the two.

Rules can be enables/disabled from other rules too (it’s way easier to do from GraalVM JS with the Helper Library) so you could have a rule you run to do the enable/disable if you don’t want to use MainUI. I think you can also do it from the Karaf Console.

2 Likes

Ahh, right, kind of obvious. It’s just the folder location. Actually that’s easy because I could just switch back and forth in my deployment script.

What I’d do is have two separate copies of my rules and migrate one to GraalVM. Then I could have my deployment script put either copy into their respective locations according to whether I’m debugging the migrated rules or going back to the old ones.

Thanks!

Hello,
so what are the steps for upgrading from oh3.4.4 to oh4.0m2 ? Or is the snapshot currently better?

Upgrading java via openhabian menu? And than upgrading to milestone build? Can I revert back to oh3.4.4 from milestone build?

what is host operating system? Here is how I did my Linux host

I am running on openhabian

I want to share that I had huge problems with Java 17 not installing on RPi 4 due to unmet dependencies and how I solved it.

$ sudo apt-get install openjdk-17-jre-headless
Some packages could not be installed.
...
The following packages have unmet dependencies:
 openjdk-17-jre-headless : Depends: libc6 (>= 2.34) but 2.28-10+rpt2+rpi1+deb10u1 is to be installed
                           Depends: libgcc-s1 (>= 3.5) but it is not going to be installed
E: Unable to correct problems, you have held broken packages.

Turns out, nothing is broken, but libc6 is held and it warns about incompatibilities if you upgrade that.
I tried upgrading from buster to bullseye but made no difference.

Then I manually downloaded Zulu Java 17, Linux 32 bit edition, and that worked.
Instructions from ChatGPT:

wget https://cdn.azul.com/zulu-embedded/bin/zulu17.42.19-ca-jre17.0.7-linux_aarch32hf.tar.gz
tar -zxvf zulu17.42.19-ca-jre17.0.7-linux_aarch32hf.tar.gz
sudo mv zulu17.42.19-ca-jre17.0.7-linux_aarch32hf /usr/lib/jvm/
sudo update-alternatives --install /usr/bin/java java /usr/lib/jvm/zulu17.42.19-ca-jre17.0.7-linux_aarch32hf/bin/java 1
sudo update-alternatives --config java
java -version

Hope this is useful to someone. At least now the error is searchable.

Edit: The correct way to upgrade probably would have eliminated the issue. Link

Wrote a similar procedure (non ChatGPT :wink:) to use Zulu on Buster earlier in this chain openHAB 4.0 Milestone discussion - Setup, Configuration and Use / News & Important Changes - openHAB Community.

Only other comment on your post is that there should be no problem with openjdk17 on Bullseye. After running OH4M1 for about a month with Buster/Zulu I upgraded to bullseye, (the non-recommended way - not with a new clean install) and changed the java back to openjdk17 with no issues. The Bullseye/openjdk17 is also the current openhabian base for a clean install of OH4, so something must have been amiss with your upgrade to Bullseye.

1 Like

any help on this?

@J-N-K is there any advise you can give me about this issue ?

Not an expert, but have transitioned two systems. The question by @Andrew_Rowe is key. Buster or Bullseye? (since you are on openhabian I’m assuming it is one or the other). As noted above the openhabian version of java17 will not work with Buster, you will need to either try zulu, do a fresh install or try to upgrade from Buster to Bullseye (kind of like open heart surgery). If you are on Bullseye just use openhabian.

As to the version, I see you are on 3.4.4. I know that fixed some specific issues. If you upgraded because of those issues I’d wait until 4.0M3 because I do not think 4.0M2 had those issues fixed. I saw somewhere it could be this weekend. I would try to avoid the snapshots only because less people use them. With a milestone there are more testers and better forum support if you have a problem.

Does that help?

edit: reversion is not officially supported, but I did manage to revert one system back to 3.4 from OH4M1. Obviously do an OH backup before you start anything.

Doesn’t openHABian already have an option to upgrade java? Sorry, it’s been a little while since I last used openHABian. I thought an upgrade to OH4 was already an option. Maybe start a new thread, put openHABian in the thread title and I’m sure Marcus will storm in and tell you everything you are doing wrong :rofl:

1 Like

It works just fine on bullseye (11) but the libc library is too old on buster (10) for most jdk 17’s to work with, including the one openHABian installs. So one will either have to upgrade their OS (which should be considered anyway) or find and manually install a jdk 17 that works on buster.

There is a limitation in openHABian where new development follows the latest OS but people don’t upgrade the OS and problems arise. There are still people out there running OH on wheezy and stretch still.

Just attempted upgrading to 4.0.0.M2 on MacOS, but have had to roll back to 3.4.4 because it seems to have got stuck in it’s head that it doesn’t have Java17. Here was the sequence:

  • Thinking I’d updated Java not that long ago, I went ahead and ran the openHAB update script to 4.0.0.M2
  • Attempted to start, got an error, quit openHAB, looked up this thread again, went and downloaded Java 17
  • Installed Java 17, attempted to start OH4, got the same error
  • Rebooted
  • Attempted to start OH4, got the same error
  • Downgraded to openHAB 3.4.4, started up, runs perfectly
  • Quit openHAB, re-ran the Java 17 installer
  • Confirmed java --version shows Java 17
  • Updated openHAB to 4.0.0.M2 again
  • Started openHAB… same error.

It’s like having attempted to start once under Java<17, it’s permanently welded that error to openHAB forever more. Or does my error just look like a JDK problem but isn’t actually?

SpaceWhale:openhab robin$ ./start.sh
Launching the openHAB runtime...
org.apache.felix.resolver.reason.ReasonException: Unable to resolve root: missing requirement [root] osgi.identity; osgi.identity=openhab-runtime-ui; type=karaf.feature; version="[4.0.0.M2,4.0.0.M2]"; filter:="(&(osgi.identity=openhab-runtime-ui)(type=karaf.feature)(version>=4.0.0.M2)(version<=4.0.0.M2))" [caused by: Unable to resolve openhab-runtime-ui/4.0.0.M2: missing requirement [openhab-runtime-ui/4.0.0.M2] osgi.identity; osgi.identity=org.openhab.ui.iconset.classic; type=osgi.bundle; version="[4.0.0.M2,4.0.0.M2]"; resolution:=mandatory [caused by: Unable to resolve org.openhab.ui.iconset.classic/4.0.0.M2: missing requirement [org.openhab.ui.iconset.classic/4.0.0.M2] osgi.wiring.package; filter:="(osgi.wiring.package=org.openhab.core.i18n)" [caused by: Unable to resolve org.openhab.core/4.0.0.M2: missing requirement [org.openhab.core/4.0.0.M2] osgi.ee; filter:="(&(osgi.ee=JavaSE)(version=17))"]]]
	at org.apache.felix.resolver.Candidates$MissingRequirementError.toException(Candidates.java:1341)
	at org.apache.felix.resolver.ResolverImpl.doResolve(ResolverImpl.java:433)
	at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:420)
	at org.apache.felix.resolver.ResolverImpl.resolve(ResolverImpl.java:374)
	at org.apache.karaf.features.internal.region.SubsystemResolver.resolve(SubsystemResolver.java:256)
	at org.apache.karaf.features.internal.service.Deployer.deploy(Deployer.java:399)
	at org.apache.karaf.features.internal.service.FeaturesServiceImpl.doProvision(FeaturesServiceImpl.java:1069)
	at org.apache.karaf.features.internal.service.FeaturesServiceImpl.lambda$doProvisionInThread$13(FeaturesServiceImpl.java:1004)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.apache.felix.resolver.reason.ReasonException: Unable to resolve openhab-runtime-ui/4.0.0.M2: missing requirement [openhab-runtime-ui/4.0.0.M2] osgi.identity; osgi.identity=org.openhab.ui.iconset.classic; type=osgi.bundle; version="[4.0.0.M2,4.0.0.M2]"; resolution:=mandatory [caused by: Unable to resolve org.openhab.ui.iconset.classic/4.0.0.M2: missing requirement [org.openhab.ui.iconset.classic/4.0.0.M2] osgi.wiring.package; filter:="(osgi.wiring.package=org.openhab.core.i18n)" [caused by: Unable to resolve org.openhab.core/4.0.0.M2: missing requirement [org.openhab.core/4.0.0.M2] osgi.ee; filter:="(&(osgi.ee=JavaSE)(version=17))"]]
	at org.apache.felix.resolver.Candidates$MissingRequirementError.toException(Candidates.java:1341)
	... 12 more
Caused by: org.apache.felix.resolver.reason.ReasonException: Unable to resolve org.openhab.ui.iconset.classic/4.0.0.M2: missing requirement [org.openhab.ui.iconset.classic/4.0.0.M2] osgi.wiring.package; filter:="(osgi.wiring.package=org.openhab.core.i18n)" [caused by: Unable to resolve org.openhab.core/4.0.0.M2: missing requirement [org.openhab.core/4.0.0.M2] osgi.ee; filter:="(&(osgi.ee=JavaSE)(version=17))"]
	at org.apache.felix.resolver.Candidates$MissingRequirementError.toException(Candidates.java:1341)
	... 13 more
Caused by: org.apache.felix.resolver.reason.ReasonException: Unable to resolve org.openhab.core/4.0.0.M2: missing requirement [org.openhab.core/4.0.0.M2] osgi.ee; filter:="(&(osgi.ee=JavaSE)(version=17))"
	at org.apache.felix.resolver.Candidates$MissingRequirementError.toException(Candidates.java:1341)

And here’s my java --version output:

openjdk 17.0.7 2023-04-18 LTS
OpenJDK Runtime Environment Zulu17.42+19-CA (build 17.0.7+7-LTS)
OpenJDK 64-Bit Server VM Zulu17.42+19-CA (build 17.0.7+7-LTS, mixed mode, sharing)

What is set in JAVA_HOME?

That was set correctly I think, but I’ve ended up being a bit more violent about it - I went to the install directory for all the old JDK versions and dumped them in the bin. Upgraded to OH4M2 and it’s running beautifully!

Although weirdly, it now starts up saying:

$ ./start.sh
Launching the openHAB runtime...
Unable to find any JVMs matching version "11".

So clearly it still really, really wants to us a wrong version of Java!

Since I migrated to OH4 M2 I am having problems with item updates (pushs) in the webui (chrome/firefox) and android/apple devices with the basic-ui.

Meaning: When I change a item on one device I do not get this pushed anymore on another device. I have to do a refresh on the device to see the changes.

With MainUI (the basic generated cards) its working fine.

I am inside kubernetes with the buildin nginx, but this was the same setup as before on OH3.

You have to look in that direction because refresh in UIs is working with OH4 installed simply either on Windows or on RPI.

Is there a different handling for basic UI and main UI regarding item updates?