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

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.

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 ...

Unable to load properties file for a dependency project inside OSGI container

Please go through the scenario given below
I have two maven projects abc-common and abc-service
abc-service has dependency on abc-common project.
abc-common is reading from a properties file named myConfig.properties as follows:
class PropertiesUtil {
.....
Properties props = new Properties();
props.load(PropertiesUtil.class.getClassLoader().getResourceAsStream("myConfig.properties"));
....
}
This works fine, when I test by creating a dummy main method in either of the projects.
But when I deploy this project into an OSGI container (JBOSS Fuse), it is not working. The prime reason is, in OSGI container, PropertiesUtil.class.getLoader() is refering to the bundle corresponding to abc-service project and I can read any file from that project, but not from abc-common project.
So the question is that, how can I change my code such that, It can read properties from class path of abc-common project in an OSGI container.
Note
I'm deploying my project as a karaf feature which lists both abc-service and abc-common bundles as dependencies.
Also, I tried different variants like
Thread.currentThread().getContextClassLoader().getResourceAsStream("myConfig.properties")
and
FrameworkUtil.getBundle(PropertiesUtil.class).getEntry("myConfig.properties.")
But none of them worked actually
In OSGi you need to use import|export of packages to allow loading resources from other bundles. Put the properties file into a package which you export from that bundle. And then from the other bundle, you import that package. You should then be able to load the resource from classpath.

OSGI Felix not exporting the src/main/resource files

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.

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/,.

Unable to wire proper bundle with my own bundle in wso2 app server

I am using wso2 Application Server 5.1.0.
I have deployed my own bundle having name demo-service which contains import-package definition in its manifest as below:
>Bundle-SymbolicName = demo-service
Import-Package = javax.sql,org.apache.commons.dbcp;version="[1.4,2)"
I tried to diagnose the most popular "uses conflict" in OSGi world for my case and I found that commons-dbcp_1.4.0.wso2v1.jar and commons-dbcp-1.4.jar both were converted to OSGi bundle by container and exported their packages with version "0.0.0" which can be observed from the output below:
>osgi> packages org.apache.commons.dbcp
org.apache.commons.dbcp; version="0.0.0"<commons-dbcp_1.4.0.wso2v1 [49]>
compass_2.0.1.wso2v2 [60] imports
org.wso2.carbon.core_4.1.0 [256] imports
org.wso2.carbon.registry.core_4.1.0 [377] imports
org.wso2.carbon.tenant.mgt_2.1.0 [434] imports
synapse-commons_2.1.1.wso2v3 [528] imports
synapse-core_2.1.1.wso2v3 [529] imports
org.apache.commons.dbcp; version="0.0.0"<commons_dbcp_1.4_1.0.0 [57]>
According to the requirement of my demo-service bundle it's not able to find
org.apache.commons.dbcp;version="[1.4,2)"
Is there any way to export the packages of commons-dbcp-1.4.jar after it gets converted from non-osgi bundle to osgi bundle because I need to make sure that my demo-service bundle should wire with commons-dbcp-1.4.jar..
In brief, any version of thirdparty jar I put in WSO2_HOME\repository\components\lib folder container exports it with version="0.0.0" .. which discourages the main concept for classloading of OSGi
please suggest if any workaround is possible in this case .. :)
Thanks ..
When a version is not specified while exporting packages OSGi defaults to version 0.0.0. In this case as it's automatically converting to osgi bundle it might not be having version explicitly specified. Sometimes this also helps to ensure that multiple versions of packages are not present.
In your case as you need to use the packages in the bundle put in repository\components\lib folder you could manually specify the version. The OSGi-fied bundles of the jars you put in repository\components\lib can be found in repository\components\dropins folder. Inside that bundle you will find the OSGi manifest file. In the manifest file manually specify the versions for the required packages under Export-Package category as follows.
org.apache.commons.dbcp;version=1.4.1
Then on startup, it would use these bundles and you should be able to export packages with specified version.

Resources