Chapter 8. Troubleshooting Dependencies
8.1. Missing dependencies
The most common issue that can arise when you deploy an OSGi bundle into the Red Hat Fuse container is that one or more dependencies are missing. This problem shows itself when you try to resolve the bundle in the OSGi container, usually as a side effect of starting the bundle. The bundle fails to resolve (or start) and a ClassNotFound
error is logged (to view the log, use the log:display
console command or look at the log file in the FUSE_HOME/data/log
directory).
There are two basic causes of a missing dependency: either a required feature or bundle is not installed in the container; or your bundle’s Import-Package
header is incomplete.
8.2. Required features or bundles are not installed
Evidently, all features and bundles required by your bundle must already be installed in the OSGi container, before you attempt to resolve your bundle. In particular, because Apache Camel has a modular architecture, where each component is installed as a separate feature, it is easy to forget to install one of the required components.
Consider packaging your bundle as a feature. Using a feature, you can package your bundle together with all of its dependencies and thus ensure that they are all installed simultaneously. For details, see Chapter 9, Deploying Features.
8.3. Import-Package header is incomplete
If all of the required features and bundles are already installed and you are still getting a ClassNotFound
error, this means that the Import-Package
header in your bundle’s MANIFEST.MF
file is incomplete. The maven-bundle-plugin
(see Section 5.2, “Modifying an Existing Maven Project”) is a great help when it comes to generating your bundle’s Import-Package
header, but you should note the following points:
-
Make sure that you include the wildcard,
*
, in theImport-Package
element of the Maven bundle plug-in configuration. The wildcard directs the plug-in to scan your Java source code and automatically generates a list of package dependencies. -
The Maven bundle plug-in is not able to figure out dynamic dependencies. For example, if your Java code explicitly calls a class loader to load a class dynamically, the bundle plug-in does not take this into account and the required Java package will not be listed in the generated
Import-Package
header. -
If you define a Blueprint XML file (for example, in the
OSGI-INF/blueprint
directory), any dependencies arising from the Blueprint XML file are automatically resolved at run time.
8.4. How to track down missing dependencies
To track down missing dependencies, perform the following steps:
-
Use the
bundle:diag
console command. This will provide information about why your bundle is inactive. See Apache Karaf Console Reference for usage information. -
Perform a quick check to ensure that all of the required bundles and features are actually installed in the OSGi container. You can use
bundle:list
to check which bundles are installed andfeatures:list
to check which features are installed. Install (but do not start) your bundle, using the
bundle:install
console command. For example:karaf@root()> bundle:install MyBundleURL
Use the
bundle:dynamic-import
console command to enable dynamic imports on the bundle you just installed. For example, if the bundle ID of your bundle is 218, you would enable dynamic imports on this bundle by entering the following command:karaf@root()> bundle:dynamic-import 218
This setting allows OSGi to resolve dependencies using any of the bundles already installed in the container, effectively bypassing the usual dependency resolution mechanism (based on the
Import-Package
header). This is not recommemded for normal deployment, because it bypasses version checks: you could easily pick up the wrong version of a package, causing your application to malfunction.You should now be able to resolve your bundle. For example, if your bundle ID is 218, enter the followng console command:
karaf@root()> bundle:resolve 218
Assuming your bundle is now resolved (check the bundle status using
bundle:list
), you can get a complete list of all the packages wired to your bundle using thepackage:imports
command. For example, if your bundle ID is 218, enter the following console command:karaf@root()> package:imports -b 218
You should see a list of dependent packages in the console window:
Package │ Version │ Optional │ ID │ Bundle Name ─────────────────────────────────────┼───────────────┼────────────┼─────┼────────────────────────────────── org.apache.jasper.servlet │ [2.2.0,3.0.0) │ resolved │ 217 │ org.ops4j.pax.web.pax-web-runtime org.jasypt.encryption.pbe │ │ resolved │ 217 │ org.ops4j.pax.web.pax-web-runtime org.ops4j.pax.web.jsp │ [7.0.0,) │ resolved │ 217 │ org.ops4j.pax.web.pax-web-runtime org.ops4j.pax.web.service.spi.model │ [7.0.0,) │ │ 217 │ org.ops4j.pax.web.pax-web-runtime org.ops4j.pax.web.service.spi.util │ [7.0.0,) │ │ 217 │ org.ops4j.pax.web.pax-web-runtime ...
-
Unpack your bundle JAR file and look at the packages listed under the
Import-Package
header in theMETA-INF/MANIFEST.MF
file. Compare this list with the list of packages found in the previous step. Now, compile a list of the packages that are missing from the manifest’sImport-Package
header and add these package names to theImport-Package
element of the Maven bundle plug-in configuration in your project’s POM file. To cancel the dynamic import option, you must uninstall the old bundle from the OSGi container. For example, if your bundle ID is 218, enter the following command:
karaf@root()> bundle:uninstall 218
- You can now rebuild your bundle with the updated list of imported packages and test it in the OSGi container.
addurl :experimental: :toc: :toclevels: 4 :numbered: