I am trying to get the org.apache.felix.http.jetty bundle working to provide a HTTP Service to my OSGi environment.
I also have the servlet-api bundle deployed, which exports the versioned packages, but does not provide the JavaServlet capability (as it probably should, based on the OSGi Alliance page on Reference Contracts).
Here's part of the MANIFEST of the servlet-api bundle
Export-Package: javax.servlet;uses:="javax.servlet.descriptor,javax.se
rvlet.annotation";version="3.1.0",javax.servlet.descriptor;version="3
.1.0",javax.servlet.annotation;uses:="javax.servlet";version="3.1.0",
javax.servlet.http;uses:="javax.servlet";version="3.1.0"
Implementation-Version: 3.1.0
Specification-Vendor: Oracle Corporation
Bundle-Name: Java Servlet API
Bundle-Vendor: GlassFish Community
Import-Package: javax.servlet;version="3.1.0",javax.servlet.annotation
;version="3.1.0",javax.servlet.descriptor;version="3.1.0",javax.servl
et.http;version="3.1.0"
The Provide-Capability header is not specified at all.
So, when I start the OSGi container, it complains with this error:
Unresolved requirements: [[org.apache.felix.http.jetty [28](R 28.0)]
osgi.contract; (&(osgi.contract=JavaServlet)(version=3.1))]
Anyone knows how this can be fixed?
You should be using org.apache.felix.http.servlet-api bundle from Felix itself.
Related
I want to convert Elasticsearch Java API Client into an OSGI bundle as it is not readily available anywhere. I tried the following command to create one on my own but it not work. I also tried maven bundle plugins but it resulted in the same error. What am I doing wrong?
jar cvfm osgi-elasticsearch-java-8.0.1.jar ./MANIFEST.txt elasticsearch-java-8.0.1.jar
The MANIFEST use is as follows:
Manifest-Version: 1.0
Bundle-Category: OSGI ELK
Bundle-Description: Elastic Search Client Bundle
Bundle-ManifestVersion: 2
Bundle-Name: OSGI ELK - HG
Bundle-SymbolicName: osgi-elk.hg
Bundle-Version: 1.7.0
Bundle-ClassPath: .,elasticsearch-java-8.0.1.jar
Export-Package: co.elastic.clients.elasticsearch, co.elastic.clients.elasticsearch.indices, co.elastic.clients.json, co.elastic.clients.json.jackson, co.elastic.clients.transport, co.elastic.clients.transport.rest_client
The following classes are not available after installing the manually created Elasticsearch Java API Client OSGI bundle to a OSGI container.
co.elastic.clients.elasticsearch -- Cannot be resolved
co.elastic.clients.elasticsearch.indices -- Cannot be resolved
co.elastic.clients.json -- Cannot be resolved
co.elastic.clients.json.jackson -- Cannot be resolved
co.elastic.clients.transport -- Cannot be resolved
co.elastic.clients.transport.rest_client -- Cannot be resolved
Subject : OSGI Kafka client bundle causes a framework exception due to missing constraint
I downloaded the kafka-clients OSGI bundle (org.apache.servicemix.bundles.kafka-clients-0.11.0.1_1.jar) from Apache ServiceMix (https://mvnrepository.com/artifact/org.apache.servicemix.bundles/org.apache.servicemix.bundles.kafka-clients/0.11.0.1_1).
Below is my pom.xml
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.kafka-clients</artifactId>
<version>0.11.0.1_1</version>
</dependency>
I used this to develop my Kafka producer code within the sflow_collector module of my application built using OSGI.
Everything compiles, no issue there.
When I run my application, I get the following error during the loading of the sflow_collector module.
org.osgi.framework.BundleException: The bundle "sflow-collector_1.0.0 [49]" could not be resolved. Reason: Missing Constraint: Import-Package: org.apache.kafka.clients.producer; version="[0.11.0,1.0.0)"
I checked the manifest of the Kafka OSGI bundle, it looks fine. I see the producer in the export list (shown in bold below).
Manifest-Version: 1.0
Bnd-LastModified: 1508749231115
Build-Jdk: 1.8.0_111
Built-By: jbonofre
Bundle-Description: This OSGi bundle wraps kafka-clients 0.11.0.1 jar file.
Bundle-DocURL: http://www.apache.org/
Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
Bundle-ManifestVersion: 2
Bundle-Name: Apache ServiceMix :: Bundles :: kafka-clients
Bundle-SymbolicName: org.apache.servicemix.bundles.kafka-clients
Bundle-Vendor: The Apache Software Foundation
Bundle-Version: 0.11.0.1_1
Created-By: Apache Maven Bundle Plugin
Export-Package:
org.apache.kafka.clients;version="0.11.0.1";uses:="org.apache.kafka.common,
org.apache.kafka.common.config,
org.apache.kafka.common.errors,
org.apache.kafka.common.internals,
org.apache.kafka.common.metrics,
org.apache.kafka.common.network,
org.apache.kafka.common.protocol,
org.apache.kafka.common.requests,
org.apache.kafka.common.utils",
org.apache.kafka.clients.admin;version="0.11.0.1";
uses:="org.apache.kafka.common,
org.apache.kafka.common.acl,
org.apache.kafka.common.annotation,
org.apache.kafka.common.config,
org.apache.kafka.common.errors",
org.apache.kafka.clients.consumer;version="0.11.0.1";
uses:="org.apache.kafka.clients.coumer.internals,
org.apache.kafka.common,
org.apache.kafka.common.config,
org.apache.kafka.common.errors,
org.apache.kafka.common.header,
org.apache.kafka.common.record,
org.apache.kafka.common.serialization",
org.apache.kafka.clients.consumer.internals;version="0.11.0.1";uses:="org.apache.kafka.clients,
org.apache.kafka.clients.consumer,
org.apache.kafka.common,
org.apache.kafka.common.errors,
org.apache.kafka.common.metrics,
org.apache.kafka.common.protocol,
org.apache.kafka.common.protocol.types,
org.apache.kafka.common.requests,
org.apache.kafka.common.serialization,
org.apache.kafka.common.utils",
org.apache.kafka.clients.producer;version="0.11.0.1";uses:="org.apache.kafka.clients.consumer,
org.apache.kafka.common,
org.apache.kafka.common.config,
org.apache.kafka.common.errors,
I am not able to fix this problem.
Any help much appreciated. Please email is any more info is required.
As you probably understood, the error message
Missing Constraint: Import-Package: org.apache.kafka.clients.producer; version="[0.11.0,1.0.0)
.. indicates that a bundle (probably your bundle) imports the 'clients.producer' package, while no bundle in the container exports that package with the given version. The version matches the kafka-clients bundle manifest that you pasted, so no problem there. My guess is that the kafka-clients bundle is not deployed in the container, and you have to deploy it as well as your own bundle.
Which container are you using? If it's Apache Karaf you might find some hints in this github project.
I'm pretty new to osgi and bndtools, but in the past couple days have managed to get jar->bundle creation working using bnd ant task, plus wrapping of our 3rd party jars as bundles (for those not already defining an 'Export-Package' in the manifest file). I must comment that bndtools seems amazing for doing all the heavy lifting when it comes to exports and imports, so thank you to your hard work on this project!
i've got two issues that maybe you can shed some light on:
1
I'm trying to get the bundles to load in felix and am immediately running into resolution errors. In this basic scenario, we have our in-house bundle called omniquery_common, which uses several 3rd party jars, including gson. when i resolve i get this:
Unable to resolve <<INITIAL>> version=null:
missing requirement Require[osgi.identity]{}{filter=(osgi.identity=omniquery_common)} [caused by:
Unable to resolve omniquery_common version=1.0.0.0:
missing requirement Require[osgi.wiring.package]{}{filter=(&(osgi.wiring.package=com.google.gson)(version>=2.2.0)(!(version>=3.0.0)))}]
To me this says omniquery_common is importing com.google.gson (of a version at least 2.2 and less than 3.0). the gson bundle is exporting version 2.2.4, so this should satisfy its dependency, but is not.
can you help me understand how i am wiring this up wrong?
manifest for omniquery_common:
Manifest-Version: 1.0
Bnd-LastModified: 1442336803995
Bundle-ManifestVersion: 2
Bundle-Name: omniquery_common
Bundle-SymbolicName: omniquery_common
Bundle-Version: 1.0.0.0
Created-By: 1.8.0_40 (Oracle Corporation)
Export-Package: com.radian6.omni.common.osgi;version="1.0.0"
Import-Package: com.google.gson;version="[2.2,3)",com.radian6.omni.commo
n.util,org.apache.commons.io;version="[1.4,2)",org.apache.commons.lang;
version="[2.6,3)",org.junit
Private-Package: com.radian6.omni.common.core
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.7))"
Tool: Bnd-2.4.1.201501161923
manifest for gson:
Manifest-Version: 1.0
Export-Package: com.google.gson;version=2.2.4, com.google.gson.annotat
ions;version=2.2.4, com.google.gson.reflect;version=2.2.4, com.google
.gson.stream;version=2.2.4, com.google.gson.internal;version=2.2.4, c
om.google.gson.internal.bind;version=2.2.4
Bundle-ClassPath: .
Built-By: inder
Bundle-Name: Gson
Created-By: Apache Maven 3.0.4
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-Vendor: Google Gson Project
Bundle-ContactAddress: http://code.google.com/p/google-gson/
Bundle-Version: 2.2.4
Build-Jdk: 1.7.0_21
Bundle-ManifestVersion: 2
Bundle-Description: Google Gson library
Bundle-SymbolicName: com.google.gson
Archiver-Version: Plexus Archiver
2
if i alter the order of the bundles in the 'run requirements' list, putting the gson bundle before omniquery_common, i then get
Unable to resolve <<INITIAL>> version=null:
missing requirement Require[osgi.identity]{}{filter=(osgi.identity=com.google.gson)}
which i find unintuitive - i would have thought the bundle order in that list would not matter...?
The order of the requirements in the -runrequirements list does matter, because if there is an error early in the list then we don't bother trying to resolve everything below it. That is: once we know that the resolution cannot succeed, we just exit and print the first error we encountered.
The second error message you copied (when you put the GSON requirement first) suggests that you simply don't have the GSON bundle in your repository. Or, it is not in a repository that is visible to the resolver. The filter (osgi.identity=com.google.gson) fails, which means there is no resource with the identity com.google.gson.
This would also explain the first error message from your own omniquery_common bundle. The resolver cannot find any bundle exporting the package com.google.gson, which would make perfect sense if the GSON bundle is not there.
So, look into the repositories you are resolving against and what their indexes contain. If GSON really does appear to be in there, then I will need further info on to figure out the problem.
Incidentally, once you have this working, you shouldn't need to list GSON explicitly at all in -runrequirements. That is the point of the resolver: we will find all your dependencies based on the packages you used.
I have an app running under Tomcat 6. The app contains/uses shared library, say Shared.jar. At some point it would copy Shared.jar with unique name, load it as an OSGi bundle into a Felix instance, and start it. In Shared.jar MANIFEST.MF there's
Import-Package: org.osgi.framework,javax.swing,javax.net,javax.net.ssl.
It's all fine with Java < 8, but with Java 8 the app itself starts fine, but starting a bundle fails with exception
Unresolved constraint in bundle [21431]: Unable to resolve 21431.0: missing requirement [21431.0] osgi.wiring.package; (osgi.wiring.package=javax.net)
What's wrong?
You need minimum Karaf 2.4 to support Java 8.
May be you would also need to add import package declaration in your pom.xml
<Import-Package>javax.net.*</Import-Package>
..but that doesn't look like the main issue, because it is working with older versions of JRE.
My project has two OSGi bundles (A and B) which need to use different versions of javax.activation — A requires version 1.1.0, while B requires 1.1.1.
By default in AEM 5.6.1, there is a bundle already installed which exports version 1.1.1, which bundle A is using. In order to make it use 1.1.0 instaed, I used boot delegation to get the javax.activation from the JRE 7 for the system bundle which is 1.1.0. I am setting this using sling.properties file in AEM 5.6.1.
If I give a version for javax.activation greater than 1.1.1 in this sling.properties file, both A and B are using the system version (even though version of import-packages is specified in the manifest.mf file); but if I give a version less than 1.1.1, both bundles use the version provided by AEM.
How can I configure my bundles so as to use different versions of javax.activation for Bundle A from Bundle B?
If you want to use exactly 1.1.0 version in bundle A, than you should specify it in A's manifest file:
Import-Package: javax.activation;version="[1.1.0,1.1.0]"
For bundle B manifest will be:
Import-Package: javax.activation;version="[1.1.1,1.1.1]"
This can be downright difficult due to the OSGI bundle resolution rules. Check out this article--I found it to be a good explanation of the various rules that apply. Specifically, check out the uses directive:
http://www.christianposta.com/blog/?p=241
Life will be much simpler if there is a way for both to use the the same version (but I know that may not always be possible).
This is from the article above:
For every Import-Package package declaration, there must be a
corresponding Export-Package with the same package
Bundles can also attach other attributes to the packages it imports or
exports. What if we added a version attribute to our example:
Bundle-Name: Bundle A Import-Package: org.apache.foo;version="1.2.0"
This means, Bundle A has a dependency on package org.apache.foo with a
minimum version of 1.2.0. Yes, you read correctly. Although with OSGI
you can specify a range of versions, if you don’t specify a range but
rather use a fixed version, it will result in a meaning of “a minimum”
of the fixed value. If there is a higher version for that same
package, the higher version will be used. So bundle A will not resolve
correctly unless there is a corresponding bundle B that exports the
required package:
Bundle-Name: Bundle B Export-Package: org.apache.foo;version="1.2.0"
Note that the reverse is not true… If Bundle B exported version 1.2.0,
Bundle A is not required to specify a version 1.2.0. It can use this
import and resolve just fine:
Bundle-Name: Bundle A Import-Package: org.apache.foo
This is because imports declare the versions they need. An exported
version does not specify anything an importing bundle must use (which
holds for any attributes, not just version). Import-Package dictates
exactly what version (or attribute) it needs, and a corresponding
Export-Package with the same attribute must exist
What happens if you have a scenario where Bundle A imports a package
and it specifies a version that is provided by two bundles:
Bundle-Name: Bundle A Import-Package: org.apache.foo;version="1.2.0"
Bundle-Name: Bundle B Export-Package: org.apache.foo;version="1.2.0"
Bundle-Name: Bundle C Export-Package: org.apache.foo;version="1.2.0"
Which one bundle does Bundle A use? The answer is it depends on which
bundle (B or C) was installed first. Bundles installed first are used
to satisfy a dependency when multiple packages with the same version
are found
Things can get a little more complicated when hot deploying bundles
after some have already been resolved. What if you install Bundle B
first, then try to install Bundle A and the following Bundle D
together:
Bundle-Name: Bundle D Export-Package: org.apache.foo;version="1.3.0"
As we saw from above, the version declaration in Bundle A (1.2.0)
means a minimum version of 1.2.0; so if a higher version was available
then it would select that (version 1.3.0 from Bundle D in this case).
However, that brings us to another temporal rule for the bundle
resolution: Bundles that have already been resolved have a higher
precedence that those not resolved
The reason for this is the OSGI framework tends to favor reusability
for a given bundle. If it’s resolved, and new bundles need it, then it
won’t try to have many other versions of the same package if it
doesn’t need to. Bundle “uses” directive
The above rules for bundle resolution are still not enough and the
wrong class could still be used at runtime resulting in a class-cast
exception or similar. Can you see what could be missing?
What if we had this scenario. Bundle A exports a package,
org.apache.foo, that contains a class, FooClass. FooClass has a method
that returns an object of type BarClass, but BarClass is not defined
in the bundle’s class space, it’s imported like this:
1 2 3 public class FooClass {
public BarClass execute(){ ... } }
Bundle-Name: Bundle A Import-Package: org.apache.bar;version="3.6.0"
Export-Package: org.apache.foo;version="1.2.0"
So far everything is fine as long as there is another bundle that
properly exports org.apache.bar with the correct version.
Bundle-Name: Bundle B Export-Package: org.apache.bar;version="3.6.0"
These two bundles will resolve fine. Now, if we install two more
bundles, Bundle C and Bundle D that look like this:
Bundle-Name: Bundle C Import-Package: org.apache.foo;version="1.2.0",
org.apache.bar;version="4.0.0"
Bundle-Name: Bundle D Export-Package: org.apache.bar;version="4.0.0"
We can see that Bundle C imports a package, org.apache.foo from Bundle
A. Bundle C can try to use FooClass from org.apache.foo, but when it
gets the return value, a type of BarClass, what will happen? Bundle A
expects to use version 3.6.0 of BarClass, but bundle C is using
version 4.0.0. So the classes used are not consistent within bundles
at runtime (i.e., you could experience some type of mismatch or class
cast exception), but everything will still resolve just fine at deploy
time following the rules from above. What we need is to tell anyone
that imports org.apache.foo that we use classes from a specific
version of org.apache.bar, and if you want to use org.apache.foo you
must use the same version that we import. That’s exactly what the uses
directive does. Let’s change bundle A to specify exactly that:
Bundle-Name: Bundle A Import-Package: org.apache.bar;version="3.6.0"
Export-Package: org.apache.foo;version="1.2.0"";uses:=org.apache.bar
Given the new configuration for Bundle A, the bundles would not
resolve correctly from above. Bundle C could not resolve, because it
imports org.apache.foo but the “uses” constraint on Bundle A specifies
that C must use the same version that A does (3.6.0) for
org.apache.bar, otherwise the bundle will not resolve when trying to
deploy. The solution to this is change the version in Bundle C for
org.apache.bar to be 3.6.0.