How to find the package dependency of an OSGi bundle - osgi

I have 2 OSGi Bundle Repositories. I want to use API to check if a bundle has any dependency problems provided the 2 obr. How can I invoke api to do that?
It seems I can use the following code with Felix API to do that. But how can I get the RepositoryAdmin object?
RepositoryAdmin repoAdmin = ...
repoAdmin.addRepository(new File("/home/chandler/ws/reliability/testParent/test.eba/target/localobr/repository.xml").toURI().toURL());
repoAdmin.addRepository(new File("/home/chandler/geronimo3/var/obr.xml").toURI().toURL());
List<Repository> repos = new ArrayList<Repository>();
for(Repository repo : repoAdmin.listRepositories()) {
repos.add(repo);
}
repos.add(repoAdmin.getSystemRepository());
repos.add(getLocalRepository(repoAdmin));
Resolver resolver = repoAdmin.resolver(repos.toArray(new Repository[0]));
Resource resources[] = repoAdmin.discoverResources("(&(presentationname=*)(symbolicname=com.chandler.app.osgi.test))");
resolver.add(resources[0]);
boolean resolved = resolver.resolve();

org.apache.felix.bundlerepository-x.y.z.jar should be installed and started in your OSGi framework. You can get RepositoryAdmin service from BundleContext instance.

Related

bundle will not start when bouncy castle is imported

I am trying to add bouncy castle as a service provider to my java product running on apache karaf.
When I am trying to start the bundle which imports bouncy castle I get an error message
java.lang.Exception: Could not start bundle mvn:com.xxx.yyy.zzz/docsservice/1.0.0-SNAPSHOT/war in feature(s) server-docs-1.0.0-SNAPSHOT: Unresolved constraint in bundle docs [245]: Unable to resolve 245.0: missing requirement [245.0] osgi.wiring.package; (&(osgi.wiring.package=org.bouncycastle.jce.provider)(version>=1.51.0))
at org.apache.karaf.features.internal.FeaturesServiceImpl.startBundle(FeaturesServiceImpl.java:472)
In the pom file I imported the package org.bouncycastle.jce.provider and I added bouncycastle as a dependency.
Also, i made all the changes described on this page,
http://karaf.apache.org/manual/latest/users-guide/security.html, see below
I put provider jar in lib/ext
I Modified the etc/config.properties configuration file to add the following property
org.apache.karaf.security.providers = xxx,yyy
org.apache.karaf.security.providers = org.bouncycastle.jce.provider.BouncyCastleProvider
I provided access to the classes from those providers from the system bundle so that all bundles can access those. I did this by modifying the org.osgi.framework.bootdelegation property in the same configuration file:
org.osgi.framework.bootdelegation = ...,org.bouncycastle*
On some forum I found another suggestion so I modified
*org.osgi.framework.system.packages.extra = * in the config.properties as well and I added here packages exported from bouncycastle
Nonetheless I wasn't able to load the bundle successfully. I looked at all the bundles loaded by karaf and none of them was exporting bouncy castle package.
What am I missing here? How can I make the bundles to start?
By adding the package to the boot delegation you made it available like java.* packages. For these you do not need an Import-Package. So one way would be to remove the Import-Package for it in your bundle. You should rather explore though if you can work without boot delegation.
Please try to remove the boot delegation and add the package to
org.osgi.framework.system.packages.extra = org.bouncycastle.jce.provider
This adds the package to the packages the system bundle exports. It should then be wired to your bundle.

Karaf missing classes in bundles

I am deploying httpclient-4.3.4.jar in deploy folder of karaf. In terminal when I use command find-class HttpClients, nothing is getting listed. When use keyword find-class HttpClient, I get only follwing classes loaded for httpclient bundle. Since some of the classes are missing I am getting java.lang.NoClassDefFoundError: org/apache/http/impl/client/HttpClients in one of my dependent bundles.
I need to know whey some classes are not available. If it is our own bundle, we can specify imports and exports to control the classes which we need to expose. But for external jars, why this is happening?
httpclient (202)
org/apache/http/HttpClientConnection.class
org/apache/http/client/HttpClient.class
org/apache/http/client/params/HttpClientParams.class
org/apache/http/client/utils/HttpClientUtils.class
org/apache/http/impl/AbstractHttpClientConnection.class
org/apache/http/impl/DefaultHttpClientConnection.class
org/apache/http/impl/SocketHttpClientConnection.class
org/apache/http/impl/client/AbstractHttpClient.class
org/apache/http/impl/client/AutoRetryHttpClient.class
org/apache/http/impl/client/ContentEncodingHttpClient.class
org/apache/http/impl/client/DecompressingHttpClient.class
org/apache/http/impl/client/DefaultHttpClient.class
org/apache/http/impl/client/SystemDefaultHttpClient.class
First, is it a valid OSGi bundle, without the required manifest entries and the right Package-Exports/Imports this won't work.
If you just drop it in the deploy folder it might get autowrapped, but this isn't always working. It's better to either take an existing Bundle or do install with:
osgi:install wrap:mvn:groupID/artifactID/version
All of this is also documented in the Karaf User Manual.
The installed bundle can be started with
start ID
where ID is the ID of the bundle just installed.
EDIT:
You definitely need to wrap the bundle in question, since it isn't a OSGi bundle yet.
So in your case do:
install wrap:mvn:org.apache.httpcomponents/httpclient/4.3.4
after the bundle is installed:
start ID
If you do a bundle:header after that you'll get a nice header definition.
The find class does show the HttpClient class in this bundle:
karaf#root()> find-class HttpClients
wrap_mvn_org.apache.httpcomponents_httpclient_4.3.4 (78)
org/apache/http/impl/client/HttpClients.class

OSGI application gets NoClassDefFoundError when using Liberty Feature

I have an OSGI bundle (awesome.test) that calls code from a jar file (testlibrary.jar). I have included the bundle as a Liberty feature (awesome.test.feature) and I have it installed on a WebSphere Application Server Liberty Profile V8.5.5. I also have an OSGI bundle (awesometest) that is a part of an OSGI application (awesometest.app) and it has an Activator class.
Here is a picture of my workspace setup
What I want to do is call methods in testlibrary.jar through methods in awesome.test, which includes testlibrary.jar in its build path. My awesome.test.feature is available to any applicaions running on my Liberty server. I want my applications to be able to use that feature to gain access to the functionality in testlibrary.jar through what I provide in awesome.test. I don't want OSGI applications to directly import packages from testlibrary.jar.
The following error appears in the binary logs when I run the application on the server:
CWWKZ0402E: A bundle exception was generated when trying to install the application awesometest.app into an OSGi framework. The error text from the OSGi framework is: Exception in awesometest.Activator.start() of bundle awesometest.
Debugging the problem finds that this exception is thrown:
java.lang.ClassNotFoundException: testlibrary.test.TestAPI
Source from TestLibraryRunner.java in awesome.test:
package awesome.test;
import testlibrary.test.TestAPI;
public class TestLibraryRunner {
public static void runNonLibTest() {
System.out.println("No Library code is being called");
}
public static void runLibTest() {
TestAPI ta = new TestAPI("This is a message.");
ta.display();
}
}
Note that runNonLibTest() will work when called from the OSGI application. Calling the TestAPI code in runLibTest from the OSGI application will cause the error above.
Source from Activator.java in awesometest:
public class Activator implements BundleActivator {
public void start(BundleContext context) throws Exception {
System.out.println("Starting...");
TestLibraryRunner.runNonLibTest();
TestLibraryRunner.runLibTest();
System.out.println("Finishing...");
}
public void stop(BundleContext context) throws Exception {
System.out.println("Stopping...");
}
}
Source from MANIFEST.MF in awesometest:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: awesometest
Bundle-SymbolicName: awesometest
Bundle-Version: 1.0.0
Bundle-Activator: awesometest.Activator
Import-Package: awesome.test,
org.osgi.framework
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Export-Package: awesometest
In summary, my OSGI application cannot touch code from the jar in the build path of the bundle included in my Liberty feature. Is there something fundamental I'm missing here? Is what I'm trying to do even possible?
Thanks
Having had the same runtime exceptions in my educational project, the simplest solution I have found is to add the used JARs under Runtime - Classpath of the imported bundle (in your case awesome.test).
I hope this late answer helps someone else.
You use the package testlibrary.test but you do not import it. You should add that package to the Import-Package statement of the bundle.
It looks like the problem is in the packaging of awesome.test. The awesometest bundle (application bundle) can find your feature code fine, but then problems occur in the feature bundle. Have you confirmed that testlibrary.jar is packaged within awesome.test (feature bundle) and that the manifest of awesome.test includes the embedded jar?
You'll also need to list your exported feature packages in your feature manifest using the IBM-API-Package header, but I assume you've already done that or your application bundle activator wouldn't be able to see the feature bundle's TestLibraryRunner.
The problem with my project was that I was not including the testlibrary.jar correctly. While it was in the build path of awesome.test, it wasn't being included with the OSGI feature bundle.
There are two possible solutions:
1.) In Eclipse, go to File > Import and choose OSGi > Java Archive into an OSGi Bundle and create a new bundle. This will put the jar in its own bundle and then awesome.test can import the packages it needs from that new bundle.
2.) In Eclipse, go to File > Import and choose OSGi > Java Archive into an OSGi Bundle and include it in an existing bundle. This has the same effect as making the jar its own bundle, but it's less modular. The advantage of this approach is that you can not export the packages from the jar and just export your own interfaces.
There is also the BND Tool. It can help automate a lot of this process. I haven't used it myself.

How to get all maven dependencies using aether?

I'm trying to fetch a maven artifact's dependencies using aether. I see a RepositorySystem.collectDependencies(), but that fetches only compile and runtime scoped dependencies. How do I fetch all dependencies for the artifact, including test and provided?
Take a look at jcabi-aether (I'm a developer), which is a wrapper around Sonatype Aether:
File repo = this.session.getLocalRepository().getBasedir();
Collection<Artifact> deps = new Aether(this.getProject(), repo).resolve(
new DefaultArtifact("junit", "junit-dep", "", "jar", "4.10"),
JavaScopes.RUNTIME
);
Assuming you are using DefaultRepositorySystemSession you may do the following:
defaultRepositorySystemSession.setDependencySelector(new DependencySelector() {
#Override
public boolean selectDependency(Dependency dependency) {
return true;
}
#Override
public DependencySelector deriveChildSelector(DependencyCollectionContext context) {
return this;
}
});
and then
CollectResult result = repositorySystem.collectDependencies(defaultRepositorySystemSession, request);
Here is an example project that does this.
These three files:
https://github.com/terraframe/Runway-SDK/tree/v1.8.0/runwaysdk-server/src/main/java/com/runwaysdk/business/generation/maven
Are a working, stand-alone, example using Aether.
It worked for a few months then I all of a sudden had an issue pop up where it would sometimes on Mac JRE throw a DependencyResolutionException on com.sun:tools.jar.
Good luck, if you decide to use it, I'm instead going to use maven-dependency-plugin dependency:build-classpath.
You can utilize DependencyFilter in Eclipses Aether. A complete version for a sample below can be found in this awesome set of Aether snippets.
DependencyFilter classpathFilter = DependencyFilterUtils.classpathFilter(JavaScopes.COMPILE, JavaScopes.PROVIDED);
CollectRequest collectRequest = new CollectRequest();
collectRequest.setRoot( new Dependency( artifact, JavaScopes.COMPILE ) );
collectRequest.setRepositories(repositories);
DependencyRequest dependencyRequest = new DependencyRequest( collectRequest, classpathFilter );
List<ArtifactResult> artifactResults =
system.resolveDependencies( session, dependencyRequest ).getArtifactResults();
UPDATE
Version 0.9.0M3 is not compatible with Maven 3.1.0, so don't use it inside Maven, i.e. in a plugin.
Take a look at this github project: https://github.com/Gemba/mvn-dd
It downloads all dependencies including test and provided.
It uses aether's library to fetch them.

using cxf in osgi: Provider org.apache.cxf.jaxws.spi.ProviderImpl not found

I am trying to publish some web services (using EndpointImpl.publish()) but I am gettings this error:
Provider org.apache.cxf.jaxws.spi.ProviderImpl not found
the cxf-bundle is installed:
[ 79] [Active ] [Created ] [ 50] Apache CXF Bundle Jar (2.4.3.fuse-01-02)
an extract of the osgi:headers shows the imported package
Import-Package =
javax.jws,
javax.persistence;version="[1.1,2)",
javax.servlet;version="[2.5,3)",
javax.xml.bind,
javax.xml.bind.annotation,
javax.xml.bind.annotation.adapters,
javax.xml.datatype,
javax.xml.namespace,
javax.xml.parsers,
javax.xml.transform,
javax.xml.transform.stream,
javax.xml.validation,
javax.xml.ws;version="[2.2,3)",
javax.xml.ws.soap;version="[2.2,3)",
javax.xml.ws.wsaddressing;version="[2.2,3)",
org.apache.commons.lang;version="[2.5,3)",
org.apache.commons.logging;version="[1.1,2)",
org.apache.cxf.jaxws;version="[2.4,3)",
org.apache.cxf.jaxws.spi;version="[2.4,3)", <--- imported
org.apache.cxf.ws.addressing;version="[2.4,3)",
org.apache.felix.gogo.commands;version="[0.10,1)",
org.apache.openjpa.enhance;version="[2.2,3)",
org.apache.openjpa.util;version="[2.2,3)",
org.osgi.framework;version="[1.5,2)",
org.osgi.service.blueprint;version="[1.0.0,2.0.0)",
org.springframework.beans.factory.xml;version="[3.0,4)",
org.springframework.context;version="[3.0,4)",
org.springframework.context.support;version="[3.0,4)",
org.w3c.dom,
org.xml.sax
Require-Bundle =
org.apache.cxf.bundle
I am not sure what else I need to do.
in case it is important. the container is a karaf 2.2.7
to address pooh's answer:
1- cxf-bundle is exporting this package: org.apache.cxf.jaxws.spi;version="2.4.3.fuse-01-02"
2- bundle was started. the error was during runtime.
3- the manifest was created using maven-bundle-plugin which should create the entire list
4- the error happen while creating a webservice endpoint:
TopologyIFPortType impl = new TopologyWS();
String addressTopology = "http://localhost:" + port
+ "/nsp/webservice/topology";
topologyEndpoint = (EndpointImpl) Endpoint.create(impl);
topologyEndpoint.getFeatures().add(new WSAddressingFeature());
topologyEndpoint.publish(addressTopology);
the complete trace:
javax.xml.ws.spi.FactoryFinder$ConfigurationError: Provider org.apache.cxf.jaxws.spi.ProviderImpl not found
at javax.xml.ws.spi.FactoryFinder$2.run(FactoryFinder.java:130)
at javax.xml.ws.spi.FactoryFinder.doPrivileged(FactoryFinder.java:220)
at javax.xml.ws.spi.FactoryFinder.newInstance(FactoryFinder.java:124)
at javax.xml.ws.spi.FactoryFinder.access$200(FactoryFinder.java:44)
at javax.xml.ws.spi.FactoryFinder$3.run(FactoryFinder.java:211)
at javax.xml.ws.spi.FactoryFinder.doPrivileged(FactoryFinder.java:220)
at javax.xml.ws.spi.FactoryFinder.find(FactoryFinder.java:160)
at javax.xml.ws.spi.Provider.provider(Provider.java:43)
at javax.xml.ws.Endpoint.create(Endpoint.java:41)
at javax.xml.ws.Endpoint.create(Endpoint.java:37)
at org.opennaas.extensions.idb.webservice.WebServiceHolder.startTopology(WebserviceControl.java:78)
at org.opennaas.extensions.idb.webservice.WebServiceHolder.start(WebserviceControl.java:60)
at org.opennaas.extensions.idb.webservice.WebserviceControl.startWebservices(WebserviceControl.java:32)
at org.opennaas.extensions.idb.shell.StartWebservices.doExecute(StartWebservices.java:16)
at org.apache.karaf.shell.console.OsgiCommandSupport.execute(OsgiCommandSupport.java:38)
at org.apache.felix.gogo.commands.basic.AbstractCommand.execute(AbstractCommand.java:35)
at org.apache.felix.gogo.runtime.CommandProxy.execute(CommandProxy.java:78)
at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:474)
at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:400)
at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108)
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:183)
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:120)
at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:89)
at org.apache.karaf.shell.console.jline.Console.run(Console.java:240)
at java.lang.Thread.run(Thread.java:679)
The version of CXF you use seem to be quite old. You should try with the current release 2.6.1. In 2.6 a lot of OSGi improvements were introduced.
You can install it using:
features:chooseurl cxf 2.6.1
features:install cxf
Don't worry, OSGi gives you full access to the information which bundle uses which package etc. You only have to know how to ask the system to give you the info you need for debugging the problem.
Unfortunately I am not familiar with karaf console commands, I am working more with ProSyst's mBeddedServer OSGi framework, but since all this is standard in OSGi, I can tell you what to look for and you can find the needed commands in karaf.
So, check the following:
1. Is Apache cxf bundle successfully installed? Is it in the "active" state?
(from your posting it seems that it is)
What is the version of the org.apache.cxf.jaxws.spi package that it exports?
This is different from the cxf bundle version!!!
In order to see the package version, look inside the manifest of the cxf bundle, and look for the Export-package header.
Is your bundle installed and started successfully? Is it in the active state?
If the error "Provider not found" appears during starting of your bundle, then your dependencies are not matching the provided packages from the cxf bundle, see point 2.
If, however, the error appears during runtime, it could have several causes:
You haven't imported all needed packages in your manifest. Try using analysis tools which can generate the manifest for you based on your source code.
or:
The code which does the publishing is located e.g. on the system classpath and uses the system classloader, which in OSGI due to modularity and security reasons doesn't have access to the bundle classloaders.
Check what is provided by the system classpath instead of as OSGi bundles. Anything there which uses Class.forName or other reflection methods won't work in the modular OSGi framework.
There are also other possibilites, but you'll need to provide more info. Was there an exception stack trace? What classes are involved in this piece of code and where on the classpath are they located? etc.

Resources