OSGI Felix not exporting the src/main/resource files - osgi

As we know that by defaul osgi export-package only export the package from src/main/java folder,
but i need the other file form src/main/resource also to be exported to use by other projects.
Below is the example of my
ProjectA (packaging type is jar)
src/main/java
x.y.z.SomeClass.java
src/main/resource
x.y.z.config.SomeConfigFile.xml
pom.xml contains
<Export-Package>
x.y.z.*,
x.y.z.config.*,
*
</Export-Package>
ProjectB (packaging type is bundle)
src/main/java
a.b.c.AnotherClass.java
src/main/resource
a.b.c.config.AnotherConfigFile.xml
pom.xml contains
<Import-Package>
x.y.z.*,
x.y.z.config.*,
*
</Import-Package>
Here my requirement is to use SomeConfigFile.xml of ProjectA into AnotherConfigFile.xml of
projectB but i always get FileNotFoundException for the above scenario.
Please help me use the src/main/resource classpath files into another osgi project.
How i can achieve the above defined scenario.

You should probably use Include-Resource instead of Import-Package. More info on the header here (in the 'headers' section): http://www.aqute.biz/Bnd/Format.

There can be several issues (I guess it is option one but the others might be useful as well)
If there is no java class usage, you must specify the required package exactly at the Import-Package section. You cannot use asterisk.
If you want to export a package that is under META-INF, in the Export-Package section you must define it with a quote and an equality character. E.g: '=META-INF.subdir'
If you want to access a resource that is in an imported package, you cannot use the bundle.getResource() function as it searches only in the current bundle. You must use the classLoader of the bundle or the or listResources function of BundleWiring.

Related

Are .kar Apache Karaf files meant to expose features only?

I am very new to OSGi and Karaf and I am still getting my head around the concepts and architecture.
My question is related to the .kar files which are created with the karaf-maven-plugin.
Does a .kar file meant to only install features into a Karaf runtime? What if we create a bundle and rename it to .kar instead of .jar. Is this a valid use case for .kar files?
Thanks
No, a kar file is much more than that as it is a mechanism to provide not only the features.xml but also any related OSGi bundles, configuration files, aso. inside a single artifact.
That's also why it contains a mandatory repository/ directory (basically containing all OSGi bundles necessary for any of the features described by the features.xml in a Maven repository-style structure) and an optional resources/ directory (containing all the additional resources referenced by a feature).
For a fully fledged example, you can have a look at the Apache Karaf framework archive:
https://repo1.maven.org/maven2/org/apache/karaf/features/framework/
That one contains all the basic resources that make up the base for a custom Karaf installation and provide the basic set of features:
META-INF/
...
META-INF/MANIFEST.MF
...
repository/
... OSGi bundles referenced by the features and the features.xml itself ...
resources/
resources/bin/
... scripts ...
resources/data/
...
resources/deploy/
...
resources/etc/
... configuration files ...
resources/lib/
... (non-OSGi) libraries needed (e.g. endorsed, extension, boot classpath) ...
resources/system/
... OSGi framework implementation(s) and related libraries ...

How to include xml files in an OSGi bundle with bndtools?

How to include an xml file in an OSGi bundle with bndtools without the use of maven ?
You can use the -includeresource or Include-Resource directive, which are explained here:
http://bnd.bndtools.org/chapters/820-instructions.html
http://bnd.bndtools.org/heads/include_resource.html
The -includeresource one is preferred. A simple example:
-includeresource: static=static
Includes the resources which are in the 'static' folder of the project into the bundle in the 'static' folder.

Replacing classes/resources with an OSGi fragment - possible without including a jar in the fragment?

We want to replace certain resources in a host OSGi bundle by adding an OSGi fragment.
As I understand it, the resources included in an OSGi fragment are merely added to the classpath of the host bundle.
There is no guarantee that if the fragment is adding a resource that already exists in the host bundle,
the resource from the fragment will be loaded: it could also still be the host version.
In order to make sure the fragment version of the resource is loaded instead of the host version,
http://wiki.osgi.org/wiki/Fragment mentions it is possible to use the Bundle-ClassPath header to specify resources as "first"(preferred).
It gives patch.jar as an example:
Bundle-ClassPath: patch.jar,.
As mentioned there: "Since patch.jar is ahead of '.' it will allow classes to be preferentially loaded from the fragment instead of the host."
I could use this technique, but this means I first have to bundle my fragment resources in a separate jar and then include this jar in the fragment bundle.
Is there a way to preferentially load classes/resources from the fragment instead of the host without having to include a jar in the fragment?
You don't have to include a jar. You can instead use a "patch" directory and then put your classes in a patch directory in the fragment.
Ok, there are a couple of ways to accomplish what you want. As I understand it, after everything is done, you want to export packages from a library bundle except for the packages located in your patch bundle.
To accomplish this, in the Manifest.MF of your library bundle, specify the explicit packages you want to export instead of '.'. You can do this with a fragment so that you won't have to modify the original bundle. Then, do the same with your patch bundle.
Another option is to use the maven-bundle-plugin to "shade" (merge) the patch bundle and the library bundle together into a new bundle. As long as the patch bundle and he library bundle have different version numbers, this will also work. Many blogs will instruct you to use the maven-shade-plugin along with the maven-bundle-plugin for this option, but they are incorrect. You can definately perform shading with the maven-bundle-plugin.
For those that are still struggling, these are the exact steps that worked for me:
Create a fragment project with the resource/class you want to replace
In the fragment's build.properties, change source.. = src/ and output.. = bin/ to source.patch/ = src/ and output.patch/ = bin/
In the fragment's manifest, add patch/ to the bundle class-path
Example:
Let's say you have com.example.ui plug-in which has a com.example.ui.MessageDialog class that you want to replace.
Create a fragment project com.example.ui.fragment
Create the MessageDialog class in the com.example.ui package (not com.example.ui.fragment);
Edit the fragment's build.properties file like this:
source.patch/ = src/
output.patch/ = bin/
In the fragment's manifest add this:
Bundle-ClassPath: patch/
In the com.example.ui manifest change the bundle class-path:
Bundle-ClassPath: patch/,.

jar bundle and its classpath in ServiceMix-karaf

I am developing 2 jar files (jar1 and jar2 - the packaging type in pom.xml of 2 jars is jar) and installed them into serviceMix. Jar1 will use some packakes from jar2.
In the manifest.mf files, i used import and export for jar1 and jar2. After installing into serviceMix 4.3.0. Everything going almost fine. From jar 1, i can use packages in jar2 (i know that by debugging the code). But the problem is here:
The structure of Jar2:
jar2:/
.
com
abc
.......(classes)
META-INF
MANIFEST.MF
FactoryContext.xml
The short version of jar2's MANIFEST.MF is
Bundle-ClassPath: .
Bundle-Name: jar2
Bundle-SymbolicName: jar2
Bundle-Version: 1.0.0
Export-Package: com.abc
Import-Package: xyz
Tool: Bnd-1.50.0
Jar1 call a method of Jar2, that method is using bellow statement
context = new ClassPathXmlApplicationContext("FactoryContext.xml");
whenever it goes to this statement, it always throws exception say that FactoryContext.xml doesn not exist. (i guest this file is not in classpath)
Do you know how to make it work?
i also posted my question on ServiceMix forum and i have got the answer from Freeman-2.
Here is the answer
You can try to put FactoryContext.xml in a unique folder like META-
INF/MyFactoryContext/FactoryContext.xml, then jar2 also export package
META-INF.MyFactoryContext, and jar1 import package META-
INF.MyFactoryContext, and then should be able to use code like
context = new ClassPathXmlApplicationContext("META-INF/
MyFactoryContext/FactoryContext.xml");
in jar1.
Here is the link
http://servicemix.396122.n5.nabble.com/question-about-jar-bundle-and-classpath-td5602052.html

osgi: import package that partially exists inside bundle

I have a package X.Y.Z that exists in 2 bundles A and B:
bundle A
package X.Y.Z
class Class1
bundle B
package X.Y.Z
class Class2
Bundle B exports package X.Y.Z.
Bundle A imports package X.Y.Z and gets an exception that his own class Class1 is not found. Should it work?
I use glassfish 3.1 with felix
No it should not work. If you import package X.Y.Z then that import will be used in preference to the bundle's own internal contents.
More generally, you have a problem known as split packages. Packages should be coherent and exported by a single bundle, not smeared across multiple bundles. You should refactor your bundle contents so that all classes belonging to package X.Y.Z are present in a single bundle.
Again, Niel is absolutely correct. But, sometimes vendors, for whatever reason will have multiple .jar files containing the same packages. This is sometimes done when they want to provide small .jar files for discreet implementations of thier product. An example of why this may be done is if they have a text-processing algorithm for an EDI document that is different than a text processing algorithm for an xml document. In this example, they may choose to create two .jar (versions 1 and 2) files containing "badlyPlannedImplementation.util" containing the different implementationing classes. Personally, I've only run into this a couple of times, but the question is how do you handle it?
When you run into the issue where you have two .jar files that export the same package and you want access to both packages classes you use a mechanism called "shading". Shading is when you take those two packages and you gather their contents together in another .jar files package. This used to be done by a maven plugin called "maven-shade-plugin" but now the functionality is part of the maven-bundle plugin.
First, create a new project, we'll call ours "badlyPlannedImplementationShaded". Then, in your project create a pom.xml file. In your dependency section, include dependencies for both of your .jar files that you're trying to shade together.
Then, add the following to your build section.
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactid>
<version>2.1.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Version>${project.version}</Bundle-Version>
<Export-Package>
badlyPlannedImplementation.util;version="1",
badlyPlannedImplementation.util;version="2"
</Export-Package>
</instructions>
</configuration>
</plugin>
Doing this will create a new bundle that contains a util package that has all of the classes from the two .jar files you were trying to use.
I hope that helps!

Resources