How to provide additional class for a package on OSGi system classpath for J2SE 1.8 profile - java-8

Inside ee.j2se-1.8 the package org.w3c.dom is included.
org.osgi.framework.system.packages = \
...
org.w3c.dom,\
...
org.osgi.framework.bootdelegation = \
...
org.w3c.*,\
org.xml.*,\
....
The bundle xml-apis_1.4.1.20140905-131237.jar contains the same package org.w3c.dom, but with one important class more ... ElementTraversal.class more.
So here my questions...
How can I provide the missing class inside my Equinox OSGi runtime?

You are suffering from the fact that people do not take packages seriously. We have a similar problem in the jta API. The version delivered by the VM is not identical to the version that is delivered as a special package.
The solution is to include the JAR with the extra packages on the class path where the framework resides. It looks like you're using bnd (good!) so this would look like:
-runpath: xml-apis__xml-apis;version="[1.4.1,2.0.0)"
If this had been a bundle with proper exports then you would have automatically gotten its exports as system packages. Looking at the packages in this bundle it seems all packages are already in the standard exports of the VM. However, if you have packages int his JAR that are not exported by the VM then you can add them as follows:
-runsystempackages: javax.xml.foo

Related

Maven Project Library Not Found

I have maven project where i am adding the dependencies which are not resolvable as below.
My servlet is as follows:
LocaleUtil is getting resolve but its sub packages are throwing error when including.
I have tried invalidate cache and restart. But this didn't work for me.
Thanks,
The packages you are trying to import are internal, non-exported packages of the bundle com.adobe.granite.i18n. In fact, that bundle only exports the following packages:
Export-Package
com.adobe.granite.i18n {version=1.0, imported-as=[1.0.0,1.1)}
com.day.cq.i18n {version=5.4.0}
You should not attempt to use private packages of a library. Limit yourself to using only the exported API.

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.

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.

I've already added tools.jar in classpath, why still java.lang.NoClassDefFoundError: com.sun.jdi.Bootstrap thrown?

I'm using the HotSwap function of javassist, it requires tools.jar in classpath, so I added -cp tools.jar when start my OSGi appliction. But when I new HotSwap() in the code of one of the bundles,
java.lang.NoClassDefFoundError: com.sun.jdi.Bootstrap
was thrown. com.sun.jdi.Bootstrap is in the tools.jar and I've already added it in classpath and also I verified it worked because if not, the following code will not work:
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
The Classloader of HotSwapper cannot load classcom.sun.jdi.Bootstrap? Then why it works properly in my Eclipse environment?(I added tools.jar into the libraries of Build path)
On why NoClassDefFoundError, any clue is appreciated.
You have to make sure the system bundle exports this package. For example in Felix the file jre.properties defines what packages are exported by the system bundle. Add the package com.sun.jdi there and it should work.
In eclipse this is done in config.ini. You can use org.osgi.framework.system.packages.extra= to define additional packages to export. I would rather not use boodelegation=* as it might export unwanted packages too. See:
http://www.eclipse.org/forums/index.php/m/734358/
http://wiki.eclipse.org/Equinox_Boot_Delegation
In Equinox, you can set Boot Delegation to * to gain acess to all class in bootclass, see this wiki for details. In 3.2, it was osgi.compatibility.bootdelegation=true in config.ini.

Resources