Debugging binding outside of OH repository

I would like to investigate @Seaside’s Unifi Protect binding, but I’m not succeeding for now… The binding is not in GitHub - openhab/openhab-addons: Add-ons for openHAB. I therefore downloaded the branch from GitHub - seaside1/unifiprotect: openHAB UniFi Protect Addon, and pasted the content in a newly created Windows directory C:\openHAB-dev\openhab-main\git\openhab-addons\bundles\org.openhab.binding.unifiprotect

PS C:\openHAB-dev\openhab-main\git\openhab-addons\bundles\org.openhab.binding.unifiprotect> dir


    Directory: C:\openHAB-dev\openhab-main\git\openhab-addons\bundles\org.openhab.binding.unifiprotect


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         7/04/2025     12:35                .github
d-----         7/04/2025     12:35                .settings
d-----         7/04/2025     12:35                img
d-----         7/04/2025     12:35                src
d-----         7/04/2025     12:41                target
d-----         7/04/2025     12:35                tools
-a----         7/04/2025     12:40           1696 .classpath
-a----         7/04/2025      9:20             40 .gitignore
-a----         7/04/2025      9:27            561 .project
-a----         7/04/2025      9:20             19 jitpack.yml
-a----         7/04/2025      9:20          14197 LICENSE
-a----         7/04/2025      9:20            370 NOTICE
-a----         7/04/2025     12:37           2657 pom.xml
-a----         7/04/2025      9:20          51399 README.md

I then ran through the necessary steps for the Demo app. At first it didn’t work, but then I changed C:\openHAB-dev\openhab-main\git\openhab-addons\bundles\org.openhab.binding.unifiprotect\pom.xml from:

<version>4.0.0-SNAPSHOT</version>

to:

<version>5.0.0-SNAPSHOT</version>

Now the Demo app runs. But if I try to debug, something fails. I’ve put a breakpoint somewhere, but when it’s reached, I see this:

Does anyone have any idea on how to fix this Source not found error?

I do this with my own binding that’s not part of the official add-ons, and have had no trouble debugging in Eclipse. That said, I haven’t tried your “trick” with copying the files into the openhab-addons folder structure.

What I do instead is that I check out/clone the other add-on using Git as normal in a separate folder. The location can be anywhere you want. Once that’s done, I do “Import → Maven Project” in Eclipse and select that folder. Once this has been imported as a separate Eclipse project, I “install it” from the root of that folder to the local Maven repo , e.g:

mvn clean install --% -T1C -DskipTests -DskipChecks -Dspotless.check.skip=true -pl :org.openhab.binding.unifiprotect

The above only works if the project is organized like the official add-ons with bundles etc., so I suspect that it won’t work with the add-on in question. You can probably install it simply with this instead:

mvn clean install --% -T1C -DskipTests -DskipChecks -Dspotless.check.skip=true

The --% in the commands above is only for Windows PowerShell. If you run this on macOS, Linux or in Windows cmd.exe, skip --%.

Once that is done, I add it as a dependency to “demo.app” in its pom.xml, and then the usual number of Refresh/Update Maven Project/Resolve (demo.app) from Eclipse until it’s good to go.

When run like this, I can put breakpoints and debug it like any other part of OH.

edit: Remember to use the actual version of the add-on that you have “installed” in the pom.xml dependency definition. Using ${project.version} as documented, only works if the add-on version is exactly the same as the OH version - which is unlikely.

edit2: It should probably be possible to point Eclipse to the correct source location in your current setup, to allow the debugger to work. I know I have “fought” with the source lookup in the past too, when things aren’t where Eclipse expects them too, but I don’t remember the details of how I’ve gotten it to do what I wanted.

Still, I’d say that it’s much “cleaner” to have the checked out add-on as a separate project. It sounds like there are so many things that can go wrong when “dropping the files” into the official add-ons repo.

Thanks for your elaborate reply!

I suppose I must run this command in the folder of my clone?

I’m not sure. But the organization of it looks very similar to other binding subfolders…?

Looking at unifiprotect/pom.xml at main · seaside1/unifiprotect · GitHub, I suppose it should be 1.2.9? Or 4.0.0-SNAPSHOT?

This is probably wrong, and I’d better put 4.0.0-SNAPSHOT in the pom.xml of the Demo app…?

I already thought it unlikely that was the way to go :wink:

Yes, but the first command is suitable to run from the “root” folder of bundles, not a bundle subfolder. The second command should work when run from a “bundle subfolder”.

I think it’s probably 4.0.0-SNAPSHOT, but when you do mvn clean install, you will see what version in “installed” into your local Maven repo. Use that version.

Yes

Sorry, I missed this, but yes: The mvn clean install command must be run from the “clone folder”.

It should be said that I’d expect a lot of potential problems if you try to import the add-on as a separate project while your “folder dump” using the same coordinates exists in the official add-ons repository. You should probably just delete the folder you copied into the official add-ons repository, and let Eclipse refresh/come to terms with this before trying to import the add-on.

If you haven’t made any other changed to the official add-ons repository, an easy way to revert it to “standard” is to run git reset --hard. Please note that this will “destroy” any uncommitted changes to the Git repo in which it is run.

Indeed, I was already planning to start from square one.

Too bad:

C:\openHAB-dev\externe-gits\unifiprotect\unifiprotect>mvn clean install -e -T1C -DskipTests -DskipChecks -Dspotless.check.skip=true
[INFO] Error stacktraces are turned on.
[INFO] Scanning for projects...
[INFO]
[INFO] Using the MultiThreadedBuilder implementation with a thread count of 8
[INFO]
[INFO] ----< org.openhab.addons.bundles:org.openhab.binding.unifiprotect >-----
[INFO] Building openHAB Add-ons :: Bundles :: UniFi Protect Binding 4.0.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[WARNING] The POM for org.eclipse.orbit.bundles:net.i2p.crypto.eddsa:jar:0.3.0.v20220506-1020 is missing, no dependency information available
[INFO]
[INFO] --- clean:3.0.0:clean (default-clean) @ org.openhab.binding.unifiprotect ---
[INFO]
[INFO] --- enforcer:3.0.0-M2:enforce (enforce-java) @ org.openhab.binding.unifiprotect ---
[WARNING] Rule 0: org.apache.maven.plugins.enforcer.RequireJavaVersion failed with message:
Detected JDK Version: 21.0.6 is not in the allowed range [17.0,18.0).
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.105 s (Wall Clock)
[INFO] Finished at: 2025-04-09T18:04:13+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-enforcer-plugin:3.0.0-M2:enforce (enforce-java) on project org.openhab.binding.unifiprotect: Some Enforcer rules have failed. Look above for specific messages explaining why the rule failed. -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-enforcer-plugin:3.0.0-M2:enforce (enforce-java) on project org.openhab.binding.unifiprotect: Some Enforcer rules have failed. Look above for specific messages explaining why the rule failed.
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:333)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:193)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:180)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:572)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
    at java.lang.Thread.run (Thread.java:1583)
Caused by: org.apache.maven.plugin.MojoExecutionException: Some Enforcer rules have failed. Look above for specific messages explaining why the rule failed.
    at org.apache.maven.plugins.enforcer.EnforceMojo.execute (EnforceMojo.java:235)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:193)
    at org.apache.maven.lifecycle.internal.builder.multithreaded.MultiThreadedBuilder$1.call (MultiThreadedBuilder.java:180)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:572)
    at java.util.concurrent.FutureTask.run (FutureTask.java:317)
    at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
    at java.lang.Thread.run (Thread.java:1583)
[ERROR]
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

The Java version seems a problem, but when I did mvn clean install on an OH4.3.x Shelly binding, there were no complaints…

This isn’t a “real Java problem”, it’s because they have configured the Maven enforcer plugin to only accept [17.0,18.0). I’ve never understood why people like to introduce such arbitrary limitations. This is just an artificial limitation caused by the exact Java version being “enforced”. I can’t see it in the pom.xml of the add-on, so I’m pretty sure it comes from OH 4.0.0 as it’s specified as the parent POM:

  <parent>
    <groupId>org.openhab.addons.bundles</groupId>
    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
    <version>4.0.0-SNAPSHOT</version>
  </parent>

It might work if you just change the version of the parent to 5.0.0-SNAPSHOT, but that might introduce other issues. It’s worth a try. Alternatively, you override the enforcer configuration in the add-on POM to be less anal.

Here is the source of the problem:

If you replicate the above in the add-on pom.xml and use e.g [17.0,99.0) instead, it should override the configuration from the parent.

edit: It seems that there’s a command-line option to disable the enforcer plugin, which can only be a good thing as far as I can tell. Try adding -Denforcer.skip=true as an argument to your mvn clean install command. Alternatively, adding this to the add-on pom.xml should also work:

<properties>
  <enforcer.skip>true</enforcer.skip>
</properties>
1 Like

I struggled a bit with where to put it, but this worked:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.openhab.addons.bundles</groupId>
    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
    <version>4.0.0-SNAPSHOT</version>
  </parent>

  <artifactId>org.openhab.binding.unifiprotect</artifactId>
  <name>openHAB Add-ons :: Bundles :: UniFi Protect Binding</name>
  <dependencies>
    <dependency>
      <version>1.2.9</version>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-core</artifactId>
      <scope>test</scope>
      <optional>true</optional>
    </dependency>
    <dependency>
      <version>1.2.9</version>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <scope>test</scope>
      <optional>true</optional>
    </dependency>
  </dependencies>
  <repositories>
    <repository>
      <id>openhab-release</id>
      <url>https://openhab.jfrog.io/artifactory/libs-release</url>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>openhab-snapshot</id>
      <url>https://openhab.jfrog.io/artifactory/libs-snapshot</url>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
  </repositories>

  <profiles>
    <profile>
      <id>standalone</id>
      <properties>
        <enforcer.skip>true</enforcer.skip>
      </properties>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <build>
        <plugins>
          <plugin>
            <groupId>org.openhab.tools.sat</groupId>
            <artifactId>sat-plugin</artifactId>
            <!--version>${sat.version}</version -->
            <configuration>
              <checkstyleProperties>tools/static-code-analysis/checkstyle/ruleset.properties</checkstyleProperties>
              <checkstyleFilter>tools/static-code-analysis/checkstyle/suppressions.xml</checkstyleFilter>
              <spotbugsExclude>tools/static-code-analysis/spotbugs/suppressions.xml</spotbugsExclude>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.commonjava.maven.plugins</groupId>
            <artifactId>directory-maven-plugin</artifactId>
            <executions>
              <execution>
                <id>directories</id>
                <phase>none</phase>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </profile>
  </profiles>
</project>

This is the end of the mvn clean install procedure:

[INFO] Installing C:\openHAB-dev\externe-gits\unifiprotect\unifiprotect\target\org.openhab.binding.unifiprotect-4.0.0-SNAPSHOT.jar to C:\Users\Erik\.m2\repository\org\openhab\addons\bundles\org.openhab.binding.unifiprotect\4.0.0-SNAPSHOT\org.openhab.binding.unifiprotect-4.0.0-SNAPSHOT.jar
[INFO] Installing C:\openHAB-dev\externe-gits\unifiprotect\unifiprotect\pom.xml to C:\Users\Erik\.m2\repository\org\openhab\addons\bundles\org.openhab.binding.unifiprotect\4.0.0-SNAPSHOT\org.openhab.binding.unifiprotect-4.0.0-SNAPSHOT.pom
[INFO] Installing C:\openHAB-dev\externe-gits\unifiprotect\unifiprotect\target\feature\feature.xml to C:\Users\Erik\.m2\repository\org\openhab\addons\bundles\org.openhab.binding.unifiprotect\4.0.0-SNAPSHOT\org.openhab.binding.unifiprotect-4.0.0-SNAPSHOT-features.xml
[INFO] Installing C:\openHAB-dev\externe-gits\unifiprotect\unifiprotect\target\org.openhab.binding.unifiprotect-4.0.0-SNAPSHOT-sources.jar to C:\Users\Erik\.m2\repository\org\openhab\addons\bundles\org.openhab.binding.unifiprotect\4.0.0-SNAPSHOT\org.openhab.binding.unifiprotect-4.0.0-SNAPSHOT-sources.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:37 min (Wall Clock)
[INFO] Finished at: 2025-04-10T09:42:36+02:00
[INFO] ------------------------------------------------------------------------

So it looks like 4.0.0-SNAPSHOT indeed.

I now altered /org.openhab.demo.app/pom.xml to this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>org.openhab.demo</groupId>
  <artifactId>org.openhab.demo.app</artifactId>
  <version>4.0.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <name>openHAB Demo :: App</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <oh.java.version>21</oh.java.version>
    <maven.compiler.release>${oh.java.version}</maven.compiler.release>
    <bnd.version>7.1.0</bnd.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.openhab.core.bom</groupId>
      <artifactId>org.openhab.core.bom.runtime</artifactId>
      <version>${project.version}</version>
      <type>pom</type>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.openhab.core.bom</groupId>
      <artifactId>org.openhab.core.bom.openhab-core</artifactId>
      <version>${project.version}</version>
      <type>pom</type>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.openhab.ui.bom</groupId>
      <artifactId>org.openhab.ui.bom.openhab-ui</artifactId>
      <version>${project.version}</version>
      <type>pom</type>
      <scope>runtime</scope>
    </dependency>

<!-- uncomment this and add the name of your binding that you want to work on -->
    <dependency>
      <groupId>org.openhab.addons.bundles</groupId>
      <artifactId>org.openhab.binding.unifiprotect</artifactId>
      <version>4.0.0-SNAPSHOT</version>
      <scope>runtime</scope>
    </dependency>
<!---->

<!-- uncomment this if you want to work on the Zigbee binding
    <dependency>
      <groupId>org.openhab.addons.bom</groupId>
      <artifactId>org.openhab.addons.bom.zigbee</artifactId>
      <version>${project.version}</version>
      <type>pom</type>
      <scope>runtime</scope>
    </dependency>
-->

  </dependencies>

  <build>
    <pluginManagement>
      <plugins>
        <!-- Use the bnd-maven-plugin and assemble the symbolic names -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <executions>
            <execution>
              <goals>
                <goal>bnd-process</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
        <!-- Required to make the maven-jar-plugin pick up the bnd generated manifest. Also avoid packaging empty Jars -->
        <!-- Moved... -->

        <!-- Setup the indexer for running and testing -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-indexer-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <localURLs>REQUIRED</localURLs>
            <attach>false</attach>
          </configuration>
          <executions>
            <execution>
              <id>index</id>
              <goals>
                <goal>index</goal>
              </goals>
              <configuration>
                <indexName>${project.artifactId}</indexName>
              </configuration>
            </execution>
            <execution>
              <id>test-index</id>
              <goals>
                <goal>index</goal>
              </goals>
              <configuration>
                <indexName>${project.artifactId}</indexName>
                <outputFile>${project.build.directory}/test-index.xml</outputFile>
                <scopes>
                  <scope>test</scope>
                </scopes>
              </configuration>
            </execution>
          </executions>
        </plugin>

        <!-- Define the version of the resolver plugin we use -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-resolver-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <failOnChanges>false</failOnChanges>
            <bndruns>
            </bndruns>
          </configuration>
          <executions>
            <execution>
              <goals>
                <goal>resolve</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <!-- Define the version of the export plugin we use -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-export-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <resolve>true</resolve>
            <failOnChanges>true</failOnChanges>
          </configuration>
          <executions>
            <execution>
              <goals>
                <goal>export</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <!-- Define the version of the testing plugin that we use -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-testing-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <executions>
            <execution>
              <goals>
                <goal>testing</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <!-- Define the version of the baseline plugin we use and avoid failing when no baseline jar exists. -->
        <!-- (for example before the first release) -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-baseline-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <failOnMissing>false</failOnMissing>
          </configuration>
          <executions>
            <execution>
              <goals>
                <goal>baseline</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <!-- Allow running openHAB demo app from a Maven/bnd task -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-run-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <includeDependencyManagement>true</includeDependencyManagement>
            <bndrun>app.bndrun</bndrun>
          </configuration>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.4.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.13.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>3.1.3</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-enforcer-plugin</artifactId>
          <version>3.5.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-install-plugin</artifactId>
          <version>3.1.3</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.4.2</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-javadoc-plugin</artifactId>
          <version>3.11.2</version>
          <configuration>
            <outputDirectory>${project.build.directory}/site</outputDirectory>
            <failOnError>!${quality.skip}</failOnError>
          </configuration>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-plugin-plugin</artifactId>
          <version>3.15.1</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-release-plugin</artifactId>
          <version>3.1.1</version>
          <configuration>
            <preparationGoals>clean install</preparationGoals>
          </configuration>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.13.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.21.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-source-plugin</artifactId>
          <version>3.3.1</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>3.5.2</version>
        </plugin>

        <!-- This plugin's configuration is used to store Eclipse m2e settings only. -->
        <!-- It has no influence on the Maven build itself. -->
        <plugin>
          <groupId>org.eclipse.m2e</groupId>
          <artifactId>lifecycle-mapping</artifactId>
          <version>1.0.0</version>
          <configuration>
            <lifecycleMappingMetadata>
              <pluginExecutions>
                <pluginExecution>
                  <pluginExecutionFilter>
                    <groupId>biz.aQute.bnd</groupId>
                    <artifactId>bnd-indexer-maven-plugin</artifactId>
                    <versionRange>[3.1.0,)</versionRange>
                    <goals>
                      <goal>index</goal>
                      <goal>local-index</goal>
                    </goals>
                  </pluginExecutionFilter>
                  <action>
                    <ignore></ignore>
                  </action>
                </pluginExecution>
              </pluginExecutions>
            </lifecycleMappingMetadata>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>

    <plugins>
      <plugin>
        <groupId>biz.aQute.bnd</groupId>
        <artifactId>bnd-run-maven-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>biz.aQute.bnd</groupId>
        <artifactId>bnd-maven-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>biz.aQute.bnd</groupId>
        <artifactId>bnd-export-maven-plugin</artifactId>
        <configuration>
          <failOnChanges>false</failOnChanges>
          <bndruns>
            <bndrun>app.bndrun</bndrun>
          </bndruns>
        </configuration>
      </plugin>
      <plugin>
        <groupId>biz.aQute.bnd</groupId>
        <artifactId>bnd-resolver-maven-plugin</artifactId>
        <configuration>
          <bndruns>
            <bndrun>app.bndrun</bndrun>
          </bndruns>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <repositories>
    <repository>
      <id>openhab-artifactory-release</id>
      <name>JFrog Artifactory Repository</name>
      <url>https://openhab.jfrog.io/openhab/libs-release</url>
      <releases>
        <enabled>true</enabled>
        <updatePolicy>never</updatePolicy>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>openhab-artifactory-snapshot</id>
      <name>JFrog Artifactory Repository</name>
      <url>https://openhab.jfrog.io/openhab/libs-snapshot</url>
      <releases>
        <enabled>false</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
        <updatePolicy>daily</updatePolicy>
      </snapshots>
    </repository>
  </repositories>

  <profiles>
    <profile>
      <id>with-bnd-resolver-resolve</id>
      <activation>
        <property>
          <name>withResolver</name>
        </property>
      </activation>
      <build>
        <pluginManagement>
          <plugins>
            <plugin>
              <groupId>biz.aQute.bnd</groupId>
              <artifactId>bnd-resolver-maven-plugin</artifactId>
              <version>${bnd.version}</version>
              <executions>
                <execution>
                  <goals>
                    <goal>resolve</goal>
                  </goals>
                  <phase>package</phase>
                </execution>
              </executions>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </profile>
    <profile>
      <id>j21</id>
      <properties>
        <oh.java.version>21</oh.java.version>
        <maven.compiler.release>${oh.java.version}</maven.compiler.release>
      </properties>
    </profile>
  </profiles>

</project>

If I open /org.openhab.demo.app/app.bndrun and filter, I now see this:

Which of those three should I drag to Run Requirements?

I haven’t tested, but I’d think that the properties could be defined at the root level of the document, not inside a profile, as indicated here.

:+1:

I’m not 100% sure on this, so don’t quote me on it, but I don’t actually think it matters which one you use. From what I’ve seen in the resulting file, only the coordinates for the dependency is copied, not the “provider”, so as long as these are of the same version, I think the result is the same.

I’ve usually used the Maven Dependencies one because it “feels most correct” (given that we have defined the add-on as a Maven dependency).

The fact that dependencies are sourced in multiple ways tells me that there probably is a way to make this work without having to specify the dependency in the demo.app POM, but I haven’t bothered to try to figure this out.

There is some “trickery” involved here - the reason for running mvn install is so that the artifact exists in the local Maven repo and thus is resolvable by Maven. But, when executing this from Eclipse, that’s not the code that is run. Instead, the local Eclipse project is used if the project is open. It is apparent because you can change the code in the local project and these changes are effective when running/debugging even if you haven’t updated the artifact with a new mvn install. But, if you close the Eclipse project, it sees that the “installed” Maven artifact is indeed used, instead of the code in the local source tree.

All I’ve learned is that as long as the version of the artifact that is “installed” and the one in the local Eclipse project are the same, this works and Eclipse lets me run/debug the local code. If I change the version of the local code, I must also do another mvn install so that this version is “resolvable” too.

So, I can’t fully explain exactly how this works, but it does work if I stick to “the rules” I’ve found.

1 Like

Bear in mind that my Eclipse knowledge is more than decade old, thus might not be fully accurate in context of opwnHAB setup.

First and foremost - Eclipse uses a workspace concept which allows to import multiple projects into one workspace, even if they are not associated with each other. You just need to checkout and make it Eclipse project - through importing it as Maven Project or similar.

Maven part is obviously related as BND resolver which handles launch files, is (as far I know) configured to look into two places - Eclipse workspace and Maven repositories.

Reason why you miss sources for the debugger comes from fact that each launch configuration has associated classpath and source lookups. By default it is 1:1, meaning that all projects and their dependencies of project within which you fire launch configuration, will be searched for the sources.
However, in case of regular Java launch configurations (probably BND as well) you can modify source lookup and add either workspace project, external folder with sources or archive with sources.

Regarding necessity to do Maven install in order to see updated code - this comes from fact that bndtools launch configuration probably detects your project through maven repository, not the workspace. I do not know exactly what logic it uses, but you may need to look on their docs. Maybe it is possible by adding associated project to core, where launch config is made, or some of BND configurations itself.

To summarise - there are several layers involved in here. First is Eclipse and its projects, second is Bndtools and its resolution logic, then finally we reach to BND itself and Maven. You need to identify a faulty place among first 3 to have it running well.

Cheers,
Łukasz

Yes, it’s clear that not all the “moving parts” involved see everything, which is why I’ve found the “hack” of “Maven installing” the artifact necessary. But once everything is resolved and the application is launched, it seems to me like the workspace has a higher priority than Maven dependencies, which explains why the “workspace project” is used as long as the project is open. If it’s closed, I assume that it “doesn’t exist in the workspace”, and thus it falls back to using the Maven provided dependency.

Most of the involved systems aren’t very well documented, M2E for example is a pain to try to figure out, so trying to figure out exactly why it behaves as it does haven’t been a priority for me, as long as I’ve found a way that works and that isn’t too cumbersome.

But, if somebody is sufficiently motivated, I’m sure it’s possible to figure out and potentially avoid having to do the “Maven install” step. It’s only required when you switch artifact version, so I can live happily with this “workaround”.

Okay, the demo app is running. However, I’m not sure how to “install” the binding. I fear that the only add-on that is shown, is not my local project…

Indeed, when I run the demo app without the below dependency, this binding is also available…

Maybe the groupId is a problem?

<dependency>
      <groupId>org.openhab.addons.bundles</groupId>
      <artifactId>org.openhab.binding.unifiprotect</artifactId>
      <version>4.0.0-SNAPSHOT</version>
      <scope>runtime</scope>
</dependency>

The binding should already be “installed”. Adding it to the BND “runtime requirements” should correspond roughly to dropping a JAR in the addons folder.

If it’s not there, check the log (the “console” Window in Eclipse). If it doesn’t show anything, enable TRACE logging by editing log4j2.xml:

        <Logger level="TRACE" name="org.openhab.binding.unifiprotect"/>

Now I don’t get the Demo App running anymore… No idea what I’m doing wrong…

I reverted back to the main branch of openhab-distro (although that apparently didn’t delete any things I had added in the Demo App…?). I then created a new branch, and started the Demo App. That worked. I then altered pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>org.openhab.demo</groupId>
  <artifactId>org.openhab.demo.app</artifactId>
  <version>4.0.0-SNAPSHOT</version>
  <packaging>pom</packaging>

  <name>openHAB Demo :: App</name>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <oh.java.version>21</oh.java.version>
    <maven.compiler.release>${oh.java.version}</maven.compiler.release>
    <bnd.version>7.1.0</bnd.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.openhab.core.bom</groupId>
      <artifactId>org.openhab.core.bom.runtime</artifactId>
      <version>${project.version}</version>
      <type>pom</type>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.openhab.core.bom</groupId>
      <artifactId>org.openhab.core.bom.openhab-core</artifactId>
      <version>${project.version}</version>
      <type>pom</type>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.openhab.ui.bom</groupId>
      <artifactId>org.openhab.ui.bom.openhab-ui</artifactId>
      <version>${project.version}</version>
      <type>pom</type>
      <scope>runtime</scope>
    </dependency>

<!-- uncomment this and add the name of your binding that you want to work on -->
    <dependency>
      <groupId>org.openhab.addons.bundles</groupId>
      <artifactId>org.openhab.binding.unifiprotect</artifactId>
      <version>4.0.0-SNAPSHOT</version>
      <scope>runtime</scope>
    </dependency>
<!-- -->

<!-- uncomment this if you want to work on the Zigbee binding
    <dependency>
      <groupId>org.openhab.addons.bom</groupId>
      <artifactId>org.openhab.addons.bom.zigbee</artifactId>
      <version>${project.version}</version>
      <type>pom</type>
      <scope>runtime</scope>
    </dependency>
-->

  </dependencies>

  <build>
    <pluginManagement>
      <plugins>
        <!-- Use the bnd-maven-plugin and assemble the symbolic names -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <executions>
            <execution>
              <goals>
                <goal>bnd-process</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
        <!-- Required to make the maven-jar-plugin pick up the bnd generated manifest. Also avoid packaging empty Jars -->
        <!-- Moved... -->

        <!-- Setup the indexer for running and testing -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-indexer-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <localURLs>REQUIRED</localURLs>
            <attach>false</attach>
          </configuration>
          <executions>
            <execution>
              <id>index</id>
              <goals>
                <goal>index</goal>
              </goals>
              <configuration>
                <indexName>${project.artifactId}</indexName>
              </configuration>
            </execution>
            <execution>
              <id>test-index</id>
              <goals>
                <goal>index</goal>
              </goals>
              <configuration>
                <indexName>${project.artifactId}</indexName>
                <outputFile>${project.build.directory}/test-index.xml</outputFile>
                <scopes>
                  <scope>test</scope>
                </scopes>
              </configuration>
            </execution>
          </executions>
        </plugin>

        <!-- Define the version of the resolver plugin we use -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-resolver-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <failOnChanges>false</failOnChanges>
            <bndruns>
            </bndruns>
          </configuration>
          <executions>
            <execution>
              <goals>
                <goal>resolve</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <!-- Define the version of the export plugin we use -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-export-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <resolve>true</resolve>
            <failOnChanges>true</failOnChanges>
          </configuration>
          <executions>
            <execution>
              <goals>
                <goal>export</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <!-- Define the version of the testing plugin that we use -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-testing-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <executions>
            <execution>
              <goals>
                <goal>testing</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <!-- Define the version of the baseline plugin we use and avoid failing when no baseline jar exists. -->
        <!-- (for example before the first release) -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-baseline-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <failOnMissing>false</failOnMissing>
          </configuration>
          <executions>
            <execution>
              <goals>
                <goal>baseline</goal>
              </goals>
            </execution>
          </executions>
        </plugin>

        <!-- Allow running openHAB demo app from a Maven/bnd task -->
        <plugin>
          <groupId>biz.aQute.bnd</groupId>
          <artifactId>bnd-run-maven-plugin</artifactId>
          <version>${bnd.version}</version>
          <configuration>
            <includeDependencyManagement>true</includeDependencyManagement>
            <bndrun>app.bndrun</bndrun>
          </configuration>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.4.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.13.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>3.1.3</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-enforcer-plugin</artifactId>
          <version>3.5.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-install-plugin</artifactId>
          <version>3.1.3</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.4.2</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-javadoc-plugin</artifactId>
          <version>3.11.2</version>
          <configuration>
            <outputDirectory>${project.build.directory}/site</outputDirectory>
            <failOnError>!${quality.skip}</failOnError>
          </configuration>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-plugin-plugin</artifactId>
          <version>3.15.1</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-release-plugin</artifactId>
          <version>3.1.1</version>
          <configuration>
            <preparationGoals>clean install</preparationGoals>
          </configuration>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.13.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.21.0</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-source-plugin</artifactId>
          <version>3.3.1</version>
        </plugin>

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>3.5.2</version>
        </plugin>

        <!-- This plugin's configuration is used to store Eclipse m2e settings only. -->
        <!-- It has no influence on the Maven build itself. -->
        <plugin>
          <groupId>org.eclipse.m2e</groupId>
          <artifactId>lifecycle-mapping</artifactId>
          <version>1.0.0</version>
          <configuration>
            <lifecycleMappingMetadata>
              <pluginExecutions>
                <pluginExecution>
                  <pluginExecutionFilter>
                    <groupId>biz.aQute.bnd</groupId>
                    <artifactId>bnd-indexer-maven-plugin</artifactId>
                    <versionRange>[3.1.0,)</versionRange>
                    <goals>
                      <goal>index</goal>
                      <goal>local-index</goal>
                    </goals>
                  </pluginExecutionFilter>
                  <action>
                    <ignore></ignore>
                  </action>
                </pluginExecution>
              </pluginExecutions>
            </lifecycleMappingMetadata>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>

    <plugins>
      <plugin>
        <groupId>biz.aQute.bnd</groupId>
        <artifactId>bnd-run-maven-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>biz.aQute.bnd</groupId>
        <artifactId>bnd-maven-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>biz.aQute.bnd</groupId>
        <artifactId>bnd-export-maven-plugin</artifactId>
        <configuration>
          <failOnChanges>false</failOnChanges>
          <bndruns>
            <bndrun>app.bndrun</bndrun>
          </bndruns>
        </configuration>
      </plugin>
      <plugin>
        <groupId>biz.aQute.bnd</groupId>
        <artifactId>bnd-resolver-maven-plugin</artifactId>
        <configuration>
          <bndruns>
            <bndrun>app.bndrun</bndrun>
          </bndruns>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <repositories>
    <repository>
      <id>openhab-artifactory-release</id>
      <name>JFrog Artifactory Repository</name>
      <url>https://openhab.jfrog.io/openhab/libs-release</url>
      <releases>
        <enabled>true</enabled>
        <updatePolicy>never</updatePolicy>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
    <repository>
      <id>openhab-artifactory-snapshot</id>
      <name>JFrog Artifactory Repository</name>
      <url>https://openhab.jfrog.io/openhab/libs-snapshot</url>
      <releases>
        <enabled>false</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
        <updatePolicy>daily</updatePolicy>
      </snapshots>
    </repository>
  </repositories>

  <profiles>
    <profile>
      <id>with-bnd-resolver-resolve</id>
      <activation>
        <property>
          <name>withResolver</name>
        </property>
      </activation>
      <build>
        <pluginManagement>
          <plugins>
            <plugin>
              <groupId>biz.aQute.bnd</groupId>
              <artifactId>bnd-resolver-maven-plugin</artifactId>
              <version>${bnd.version}</version>
              <executions>
                <execution>
                  <goals>
                    <goal>resolve</goal>
                  </goals>
                  <phase>package</phase>
                </execution>
              </executions>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </profile>
    <profile>
      <id>j21</id>
      <properties>
        <oh.java.version>21</oh.java.version>
        <maven.compiler.release>${oh.java.version}</maven.compiler.release>
      </properties>
    </profile>
  </profiles>

</project>

Then I added the dependency marked Maven Dependencies, “resolved”, and clicked Debug OSGi. Then I got this log:

____________________________
Welcome to Apache Felix Gogo

g! apr 12, 2025 1:36:21 P.M. org.apache.cxf.bus.osgi.CXFExtensionBundleListener addExtensions
INFO: Adding the extensions from bundle org.apache.cxf.cxf-rt-frontend-jaxrs (50) [org.apache.cxf.jaxrs.JAXRSBindingFactory]
apr 12, 2025 1:36:21 P.M. org.apache.cxf.bus.osgi.CXFExtensionBundleListener addExtensions
INFO: Adding the extensions from bundle org.apache.cxf.cxf-rt-rs-sse (52) [org.apache.cxf.transport.sse.SseProvidersExtension]
apr 12, 2025 1:36:21 P.M. org.apache.cxf.bus.osgi.CXFExtensionBundleListener addExtensions
INFO: Adding the extensions from bundle org.apache.cxf.cxf-rt-transports-http (54) [org.apache.cxf.transport.http.HTTPTransportFactory, org.apache.cxf.transport.http.HTTPWSDLExtensionLoader, org.apache.cxf.transport.http.policy.HTTPClientAssertionBuilder, org.apache.cxf.transport.http.policy.HTTPServerAssertionBuilder, org.apache.cxf.transport.http.policy.NoOpPolicyInterceptorProvider]
apr 12, 2025 1:36:21 P.M. org.apache.cxf.bus.blueprint.NamespaceHandlerRegisterer register
INFO: Aries Blueprint packages not available. So namespaces will not be registered
apr 12, 2025 1:36:21 P.M. org.apache.cxf.bus.blueprint.NamespaceHandlerRegisterer register
INFO: Aries Blueprint packages not available. So namespaces will not be registered
apr 12, 2025 1:36:21 P.M. org.apache.cxf.bus.blueprint.NamespaceHandlerRegisterer register
INFO: Aries Blueprint packages not available. So namespaces will not be registered
apr 12, 2025 1:36:21 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider com.ctc.wstx.stax.WstxEventFactory of service javax.xml.stream.XMLEventFactory in bundle com.fasterxml.woodstox.woodstox-core
apr 12, 2025 1:36:21 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider com.ctc.wstx.stax.WstxInputFactory of service javax.xml.stream.XMLInputFactory in bundle com.fasterxml.woodstox.woodstox-core
apr 12, 2025 1:36:21 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider com.ctc.wstx.dtd.DTDSchemaFactory of service org.codehaus.stax2.validation.XMLValidationSchemaFactory in bundle com.fasterxml.woodstox.woodstox-core
apr 12, 2025 1:36:21 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider com.ctc.wstx.msv.RelaxNGSchemaFactory of service org.codehaus.stax2.validation.XMLValidationSchemaFactory in bundle com.fasterxml.woodstox.woodstox-core
apr 12, 2025 1:36:21 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider com.ctc.wstx.msv.W3CSchemaFactory of service org.codehaus.stax2.validation.XMLValidationSchemaFactory in bundle com.fasterxml.woodstox.woodstox-core
apr 12, 2025 1:36:21 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider com.ctc.wstx.stax.WstxOutputFactory of service javax.xml.stream.XMLOutputFactory in bundle com.fasterxml.woodstox.woodstox-core
apr 12, 2025 1:36:21 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.apache.aries.jax.rs.whiteboard.internal.client.ClientBuilderImpl of service javax.ws.rs.client.ClientBuilder in bundle org.apache.aries.jax.rs.whiteboard
apr 12, 2025 1:36:21 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl of service javax.ws.rs.ext.RuntimeDelegate in bundle org.apache.aries.jax.rs.whiteboard
apr 12, 2025 1:36:21 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.apache.cxf.jaxrs.sse.client.SseEventSourceBuilderImpl of service javax.ws.rs.sse.SseEventSource.Builder in bundle org.apache.aries.jax.rs.whiteboard
apr 12, 2025 1:36:22 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.eclipse.jetty.http.Http1FieldPreEncoder of service org.eclipse.jetty.http.HttpFieldPreEncoder in bundle org.eclipse.jetty.http
apr 12, 2025 1:36:22 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.eclipse.jetty.http2.hpack.HpackFieldPreEncoder of service org.eclipse.jetty.http.HttpFieldPreEncoder in bundle org.eclipse.jetty.http2.hpack
apr 12, 2025 1:36:22 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.eclipse.jetty.websocket.common.extensions.identity.IdentityExtension of service org.eclipse.jetty.websocket.api.extensions.Extension in bundle org.eclipse.jetty.websocket.common
apr 12, 2025 1:36:22 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.eclipse.jetty.websocket.common.extensions.fragment.FragmentExtension of service org.eclipse.jetty.websocket.api.extensions.Extension in bundle org.eclipse.jetty.websocket.common
apr 12, 2025 1:36:22 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.eclipse.jetty.websocket.common.extensions.compress.PerMessageDeflateExtension of service org.eclipse.jetty.websocket.api.extensions.Extension in bundle org.eclipse.jetty.websocket.common
apr 12, 2025 1:36:22 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.eclipse.jetty.websocket.common.extensions.compress.DeflateFrameExtension of service org.eclipse.jetty.websocket.api.extensions.Extension in bundle org.eclipse.jetty.websocket.common
apr 12, 2025 1:36:22 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.eclipse.jetty.websocket.common.extensions.compress.XWebkitDeflateFrameExtension of service org.eclipse.jetty.websocket.api.extensions.Extension in bundle org.eclipse.jetty.websocket.common
apr 12, 2025 1:36:22 P.M. org.apache.aries.spifly.BaseActivator log
INFO: Registered provider org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer of service javax.servlet.ServletContainerInitializer in bundle org.eclipse.jetty.websocket.server
org.openhab.core.storage.json [org.openhab.core.storage.json.internal.JsonStorage] ERROR : Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@761b9314'. Root cause is: Failed parsing 'Apr 7, 2025, 9:48:46 AM' as Date; at path $.sessions[0].createdTime
13:36:33.923 [WARN ] [ce.jetty.internal.JettyServerWrapper] - Can't create temporary directory for OsgiContextModel{HS,id=OCM-33,name='context:712658526',path='/',bundle=org.apache.felix.webconsole,context=WebContainerContextWrapper{bundle=org.apache.felix.webconsole_4.7.2 [56],contextId='context:712658526',delegate=org.apache.felix.webconsole.internal.servlet.OsgiManagerHttpContext@2a7a4e5e}}: C:\Users\Erik\AppData\Local\Temp\ROOT\context:712658526
13:36:35.140 [INFO ] [otect.internal.model.UniFiProtectNvr] - Initializing the binding, with config: UniFiProtectNvrThingConfig [host=192.168.1.1, username=openhab,  password=*************, refresh=60, eventsTimePeriodLength=30, thumbnailWidth=640.0, imageFolder=C:\Users\Erik\AppData\Local\Temp\, g4SnapshotWidth=3840, g4SnapshotHeight=2160, defaultSnapshotWidth=1920, defaultSnapshotHeight=1080, watchDog=true, g4SnapshotWidthAsString=3840, g4SnapshotHeightAsString=2160, defaultSnapshotWidthAsString=1920, defaultSnapshotHeightAsString=1080]
13:36:35.647 [WARN ] [ax.web.service.spi.model.ServerModel] - ServletModel{id=ServletModel-42,name='cxf-servlet',urlPatterns=[/*],contexts=[{WB,OCM-1,default,/}]} can't be registered now in context / under "/*" mapping. Conflict with ServletModel{id=ServletModel-39,name='/',urlPatterns=[/*],contexts=[{WB,OCM-1,default,/}]}.
13:36:35.647 [WARN ] [ax.web.service.spi.model.ServerModel] - Skipped registration of ServletModel{id=ServletModel-42,name='cxf-servlet',urlPatterns=[/*],contexts=[{WB,OCM-1,default,/}]} because of existing mappings. Servlet will be added as "awaiting registration".
13:37:29.137 [WARN ] [.io.rest.auth.internal.TokenResource] - Couldn't find a user with a session matching the provided refresh_token
13:37:29.140 [WARN ] [.io.rest.auth.internal.TokenResource] - Token issuing failed: invalid_grant
13:37:29.609 [ERROR] [re.storage.json.internal.JsonStorage] - Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@702075b4'. Root cause is: Failed parsing 'Apr 7, 2025, 9:49:24 AM' as Date; at path $.timestamp
13:38:02.508 [ERROR] [re.storage.json.internal.JsonStorage] - Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@761b9314'. Root cause is: Failed parsing 'Apr 7, 2025, 9:48:46 AM' as Date; at path $.sessions[0].createdTime
13:38:02.515 [ERROR] [re.storage.json.internal.JsonStorage] - Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@761b9314'. Root cause is: Failed parsing 'Apr 7, 2025, 9:48:46 AM' as Date; at path $.sessions[0].createdTime
13:38:02.517 [INFO ] [p.auth.internal.AuthorizePageServlet] - First user account created: ontwikkelerik
13:38:30.029 [ERROR] [re.storage.json.internal.JsonStorage] - Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@702075b4'. Root cause is: Failed parsing 'Apr 7, 2025, 9:49:24 AM' as Date; at path $.timestamp
13:38:30.035 [ERROR] [re.storage.json.internal.JsonStorage] - Couldn't deserialize value 'org.openhab.core.storage.json.internal.StorageEntry@702075b4'. Root cause is: Failed parsing 'Apr 7, 2025, 9:49:24 AM' as Date; at path $.timestamp

I had to make a new user in the GUI, but my previously created things were still there. The NVR claims to be online, but the camera didn’t. Trying to disable and then enable it again failed. Removing it as well:

As you can see, there are no logs of any of this…

I’ve installed the binding locally in my Eclipse installation to test this. I don’t own any of these cameras, so I can’t test if the binding itself is working as it should, but everything looks fine. The binding comes up as installed, and I can debug the code:

I had to do a couple of small changes in the pom.xml of the add-on to make it work though:

 pom.xml | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index bf0e4c4..a6ccbaf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,6 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-v4_0_0.xsd">
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 
   <modelVersion>4.0.0</modelVersion>
 
@@ -10,6 +10,10 @@
     <version>4.0.0-SNAPSHOT</version>
   </parent>
 
+  <properties>
+    <enforcer.skip>true</enforcer.skip>
+  </properties>
+
   <artifactId>org.openhab.binding.unifiprotect</artifactId>
   <name>openHAB Add-ons :: Bundles :: UniFi Protect Binding</name>
   <dependencies>

It turns out that the HTTP links in the POM were no longer valid, so I had to switch to HTTPS.

When it comes to the functionality of the add-on itself, I have no way to test this without a camera. But, all I added to my “demo.app” POM was this:

    <dependency>
      <groupId>org.openhab.addons.bundles</groupId>
      <artifactId>org.openhab.binding.unifiprotect</artifactId>
      <version>4.0.0-SNAPSHOT</version>
      <scope>runtime</scope>
    </dependency>

The whole BND/Maven combo in Eclipse has some “moody” behavior though, regardless of this plugin. So, I’ve found some “routines” for how to make it behave that might explain the difference in our success.

First of all, after I’ve modified the POM for “demo.app”, I rightclick the project and select Maven -> Update Project.... Once that is done and no errors are shown, I open the app.bndrun file, drags the new dependency to “Run Requirements”. I then save, wait for it to complete all processing (so that nothing is happening in the lower right corner of Eclipse). Only then do I press “Resolve”, and selects “Update” after the resolution has succeeded. If it doesn’t succeed, the cause must be found and this must be repeated. Once it has been successfully resolved/updates, I save it again. When it’s done with all its tasks after the last save, I launch it with “Debug OSGi”.

I’m not claiming that all these steps are necessary, I’m just so tired of fighting this system that I find it less frustrating to do these things that seems to work every time over fighting with all kind of strange behavior.

This shouldn’t be necessary, but not everything will be “reset” if you check out another commit. Only the files that are a part of the git repo are changed, and files that aren’t checked in (typically configuration files, JSONDB files etc.) will remain, which explains why some things have been reset while others haven’t.

Did you modify log4j2.xml as I suggested? That file is checked in to Git, so it would have been overwritten by your checkout anyway, so you’d need to repeat it. As long as the binding is set to TRACE there, you should se a whole lot of details about the binding in the log.

When it comes to the JSONDB errors you get, it looks to me like some kind of OH version conflict. By that, I mean that some of these entries have been created by a different OH version and are no longer valid. You can easily modify the JSONDB manually from within Eclipse and delete problematic entries, just make sure to do it when “demo.app” isn’t running, or your changes will be overwritten:

I’m not sure if you’re aware, but there’s a long standing bug with managed Things in “demo.app”. They only work right after you add them, if you restart the “demo.app” they will never come online and removing them will just hang forever. You must stop “demo.app” and remove them manually from the JSONDB in /org.openhab.demo.app/runtime/userdata/jsondb/org.openhab.core.thing.Thing.json. To have Things that work with “demo.app” after restart, you must define them in *.things files instead.

There is a thread about this on the forum, apparently this bug is due to some issues with start levels, but it seems that nobody that knows enough about how this works cares to fix it.

@ErikDB Did you give up or did you get it working?

Neither. :slight_smile: I just haven’t had the time yet to further toy around. But I’ll share my feedback as soon as I have been able to gather any.