Binding dependencies - compile vs provided

I’m updating the dependencies needed by the doorbird binding. I’m having some confusion about the use of the compile versus provided scope.

Some background:

  • the doorbird binding depends directly on two libs: jna and lazysodium-java.
  • lazysodium-java currently is not OSGI-compliant, however, the author has agreed to make the next release OSGI-compliant and available for download on JCenter.
  • lazysodium-java contains a bunch of native crypto code for a variety of platforms, so it is pretty large.

The current pom looks like this:

  <properties>
    <dep.noembedding>jna</dep.noembedding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.goterl.lazycode</groupId>
      <artifactId>lazysodium-java</artifactId>
      <version>4.0.1</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>net.java.dev.jna</groupId>
      <artifactId>jna</artifactId>
      <version>5.4.0</version>
      <scope>compile</scope>
    </dependency>
  </dependencies>

And the current feature.xml looks like this:

	<feature name="openhab-binding-doorbird" description="Doorbird Binding" version="${project.version}">
		<feature>openhab-runtime-base</feature>
		<feature>openhab-runtime-jna</feature>
		<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.doorbird/${project.version}</bundle>
	</feature>

There are a few things I’m confused about:

  1. Why does jna use the compile scope. That causes all the jna classes to be included in the binding jar file, which seems to unnecessarily increase the size of the binding jar file. And, if there are multiple bindings that uses jna, won’t they all redundantly include the same classes (assuming they’re using the same jna version).

  2. I don’t understand the <dep.noembedding>jna</dep.noembedding> property in the pom. What is the purpose of this?

  3. I see the systeminfo binding has this in its feature.xml. Should my feature.xml also include this, assuming I’m using the same jna version 5.5.0 (which will be the case)?

    <bundle dependency="true">mvn:net.java.dev.jna/jna/5.5.0</bundle>
  1. If the lazysodium-java author is making his library OSGI-compliant and available for download from JCenter, can/should I convert the scope to provided, then reference the library in my feature.xml? If I continue to use compile, won’t that needlessly include all the lazysodium-java classes and resources in the binding jar?

One reason I bring this up is because currently the binding jar is ~2 MB with all these extra classes, but only 50k when those classes are removed.

Hey Mark,
As you noticed scopes are influencing couple of places, I will try to answer them.

To give you short summary there are couple of plugins which are executed during the build:

  • bnd - manifest generator
  • karaf - feature generator
  • others …
    Normally scope is interpreted mainly for compile time and propagation of selected dependencies. Because there are two plugins which are not aligned scopes start to come into play. You started to use both since you used template project created by scripts available in addons repository

The bnd plugin will process dependant classes and calculate manifest for your bundle and can also do some nasty things if your dependencies are not OSGi-ready.
At the same time feature descriptor which is generated by second plugin makes use of scopes to attach selected bundles to requirements which needs to be placed into runtime before your bundle will be run.

Now, getting point after the point:

  1. My rough guess here is that bnd plugin is trying to do it best and copy classes which do not have proper OSGi metadata to your bundle which will have such metadata.
  2. The dep.noembedding property is dedicated for bnd so it does not embed jna directly in your bundle but places manifest entries forcing presence of it at the runtime.
  3. The feature generator is fairly complex and it depends on scopes - there is short description of settings in documentation which can be compared with defaults inherited from addons parent pom.
  4. If libsodium is valid dependency then compile scope should make both bnd and karaf plugin threat it properly. First will generate valid import statements in bundle manifest and second will pull it into descriptor as <bundle> element.

Best regards,
Łukasz

@splatch Thanks for your feedback! I appreciate you helping me get through this…

Oh, yeah, I know this all too well from the first iteration of my binding. :cry: Fortunately, the developer of the dependency was kind enough to build the latest version of his libraries to be OSGI-compliant… Which is what prompted my questions here.

I understand this w.r.t. the lazysodium-java dependency, because until now that library was not OSGI-compliant. However, jna is OSGI-compliant, so I don’t understand why it wants to embed those classes with my bundle.

I agree, and that’s what I thought. And, while that’s what the name noembedding would suggest, that’s not what is actually happening. All the jna classes are being copied into my bundle. That’s why I removed the dep.noembedding from my pom, and changed the jna scope from compile to provided.

Totally agree with that! :wink:

I changed all my dependencies in feature.xml to this, as all 3 dependencies are OSGI-compliant. I still don’t know if this is the right way to do it.

		<bundle dependency="true">mvn:net.java.dev.jna/jna/5.5.0</bundle>
		<bundle dependency="true">mvn:co.libly/resource-loader/1.3.7</bundle>
		<bundle dependency="true">mvn:com.goterl.lazycode/lazysodium-java/4.2.5</bundle>

Compile causes all the classes of the dependencies to be embedded in my binding’s jar file. Definitely not what I want if the libraries are OSGI-compliant. Right?