The sequence of steps described in this book's chapters guided you in constructing the case study. If you have followed these steps faithfully, you should not have encountered any major issues in building the components of this project.
As I have worked on this application, starting from scratch, going through the same steps, I've written the issues that I've encountered down here. I have also added a few that I had seen earlier.
This is by far not a complete list of the things that can possibly go wrong; the online forums and FAQ pages hold a wealth of information and answers to problems that other beginners and more advanced users have encountered. Be sure to consult those useful resources when you're stuck!
We'll also look at a few ways to troubleshoot your application to find hints on what's causing it to misbehave, as part of a root cause analysis activity.
The following are the common pitfalls that we'll look at in this chapter:
We'll also look at the following troubleshooting tips:
This section describes some of the issues that may be encountered when developing an application on an OSGi framework in general and on the Felix framework in specific. Be sure to also read the next section, which shows a few ways to investigate your issue in an attempt to discover the root cause.
I've created a bundle which includes a BundleActivator
implementation and installed it onto the OSGi framework. When I start the bundle, I'm expecting a debug message to be printed, but I get none.
The framework knows which class to use as the bundle activator through the Bundle-Activator
entry in the manifest.
If you're using Maven to build your project, as described in this book, to assist you in constructing the bundle OSGi headers, then the first thing to check is whether your bundle activator class is declared in the maven-bundle-plugin
configuration of the POM build plugins section. Here's an example of the test.MyActivator
activator:
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<!-- ... -->
<Bundle-Activator>test.MyActivator</Bundle-Activator>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
Refer to Chapter 5, The Book Inventory Bundle, for a review on how to write a bundle activator and how to declare it for inclusion as part of the bundle OSGi manifest headers.
If you're not using a tool to help you generate your OSGi headers, which is not recommended because manual header construction can be very tedious and error prone, then you should double-check the Bundle-Activator
entry in the manifest. The Bundle-Activator
manifest entry for the previous example would look like the following:
Bundle-Activator: test.MyActivator
After having installed a bundle onto Felix, I've modified the source code, re-built and deployed it, and then updated it in Felix using the update
command. But it looks like the old classes are still being used.
Okay, it's silly, but just in case, it's worth clearing this doubt first: if you have a large number of bundles installed on your framework, it's easy to type the wrong bundle ID in your update command without paying attention.
Double-check if the bundle ID is the right one by listing the installed bundles using the lb
command on the shell console.
In case you're not using the OBR service and instead have installed your bundle with a direct URL using the install <URL>
command, make sure that you're still deploying to that same URL.
When a bundle is installed using a URL, the framework downloads it and keeps that location for future updates. This location can be overridden by specifying a new location URL when updating the bundle (refer to the section on the update
command in Chapter 3,Felix Gogo).
In the case where the OBR service is used, the URL that is given to the bundle has an obr://
scheme. When this URL is opened for updates, the open stream request is intercepted and the newest compatible version of that bundle is loaded. However, when the bundle is installed using, for instance, a file://
or http://
scheme URL, the same target location is used every time.
If you've changed the bundle version after making those modifications, the deployed bundle is now located at a different URL because the bundle version is typically part of the bundle JAR name.
On Felix, you can find out the source location of a bundle by using the lb -l
command and flag.
If you are using the OBR to update your bundles, make sure you've refreshed the OBR before you update the bundle! Use the repos refresh <url>
command to instruct the OBR service to get a fresh listing of the bundles deployed to that repository.
This does not apply to private classes, that is, those that are visible and used only within the bundle.
Classes that are accessible from other bundles, public classes that are in an exported package, can be used by other bundles in the framework. If another bundle depends on a package exported by your bundle and references one of those classes, there are cases where this reference does not get updated.
To request the framework to update those references to exported packages, you use the refresh
command either by refreshing all the bundles (without any parameters) or by refreshing a selected set of bundles (refresh<id> . . .
).
I'm trying to use the OSGi Bundle Repository to update my bundle. I install and deploy my bundle using the maven-bundle-plugin
, but when I list the bundles in the OBR using the obr:list
command, my bundle doesn't show up.
By default, the maven-bundle-plugin
doesn't update the remote repository when the bundle is deployed. If you look closely at the build logs, you'll find the following message towards the end, a bit before the build successful message:
[INFO] Remote OBR update disabled (enable with -DremoteOBR)
To enable the remote OBR update during the deploy cycle, include the -DremoteOBR
directive on the command line or the<remoteOBR />
instruction in the plugin configuration.
We've set the<remoteOBR/>
instruction in the POM in this book. Here's an example of how to enable it using the command-line directive:
mvn -DremoteOBR clean deploy
Now this works well in the case when the project packaging is set to bundle:
<project>
<!-- ... -->
<packaging>bundle</packaging>
If it's not the case, refer to the bundle online documentation for the configuration required to enable projects with other packaging types for bundle deploy.
Also refer to Chapter 5 for a review on how to set up your distributionManagement
configuration for bundle deploy.
I have a dependency on a library that doesn't have any OSGi entries in its manifest. When I install it on the framework, the packages it holds are not registered and my dependency is not satisfied.
In Chapter 13, Improving the Graphics, we've looked at one way of adding the missing OSGi manifest entries, the manual way. Basically, it consists of inspecting the package contents of the Java Archive and creating the bundle manifest based on those.
This is only suitable for the simplest cases, namely, the ones where the JAR being modified doesn't have external dependencies (or where you deem those dependencies can be ignored), and where the resulting manifest entries are simple enough to be safely filled manually.
For more complex cases, it's recommended to use a tool to generate the manifest entries. Luckily, such a tool exists.
The maven-bundle-plugin
that we've used in this book as part of the build process is based on the BND tool created by Peter Kriens (OSGi Technical Officer). BND is a powerful tool that helps in creating and diagnosing OSGi bundles.
A more detailed set of documentation (as well as the download links) is available on the tool's web page (http://www.aqute.biz/Code/Bnd).
The following instructions only target to solve the specific problem described here, but the tool provides a larger set of useful features. The version of the BND tool available at the writing of this is 0.0.384
.
Let's take the example of the json
JAR we worked with in Chapter 13. If you run the following command:
java -jar bnd-0.0.384.jar wrap json-20090211.jar
The tool will analyze the contents of the JAR and generate json-20090211.bar
a new archive that contains the modified manifest file.
Unzip the archive and take a look at the generated manifest:
Manifest-Version: 1.0 Export-Package: org.json Bundle-Version: 0 Tool: Bnd-0.0.384 Bnd-LastModified: 1279997110578 Bundle-Name: json-20090211 Bundle-ManifestVersion: 2 Created-By: 1.6.0_10-rc (Sun Microsystems Inc.) Import-Package: org.json;resolution:=optional Bundle-SymbolicName: json-20090211 Originally-Created-By: 1.6.0_07 (Sun Microsystems Inc.)
Most of the legwork is already done for you; there's just a few additional steps to make it complete. The previously highlighted lines show the entries to be modified:
Bundle-Version
to be that of the artifact (in this case, 20090211). Bundle-SymbolicName
, removing the version from it. This will allow a straightforward upgrade in the framework when a newer version of the artifact is available. Optionally, you can also modify it to be fully qualified (org.json).The following listing shows the updated manifest:
Manifest-Version: 1.0 Export-Package: org.json Bundle-Version: 20090211 Tool: Bnd-0.0.384 Bnd-LastModified: 1279997110578 Bundle-Name: json-20090211 Bundle-ManifestVersion: 2 Created-By: 1.6.0_10-rc (Sun Microsystems Inc.) Import-Package: org.json;resolution:=optional Bundle-SymbolicName: org.json Originally-Created-By: 1.6.0_07 (Sun Microsystems Inc.)
All that's left is to repackage the artifact, optionally changing its extension to .jar
.
I've installed a bundle using the obr:deploy
command, which has failed for some reason, but now I get an error message "No impl service available" for every command I run on the shell.
This problem will occur if the install has caused the shell service to stop and it was unable to start again. The easiest way to fix this is to reset the environment.
To reset the environment to the way it was initially, delete the bundle-cache
directory. You'll need to reinstall the bundles that you had added. For that, you can use a script such as the one I have used in Chapter 8,Adding a Command-Line Interface.
I want to check the logs so I've tried the log command, but I'm getting a "No LogReaderService available" error message:
g! log info
No LogReaderService available
The availability of the log
command does not necessarily mean that a Log Service or that a Log Reader Service is installed. It merely provides a means to access the installed Log Reader Service's stored log entries.
This message means that an active Log Reader Service was not found on the framework. You need to install and start one.
Refer to Chapter 10, Improving the Logging, for more details on the Log Service and how to install the simple Felix Log Service and Log Reader service implementations.
I've tried adding a remote OBR to my list of repositories using the repos add
command, but I get an error message and the URL doesn't show in the repos list
command output.
First of all, double-check that the URL that you're using is valid, that is, it's well formed and actually points to a repository file.
A quick check is to point your web browser to that URL; you should be able to see the repository XML contents. If your browser cannot load that file, it means that the URL is no good.
Another possibility for this problem could be the format of the XML file located by the URL. The OBR service expects the repository descriptor to have a specific format. There are some repositories that do not follow this format and cannot be used with the Felix Bundle Repository service.
As a next step to the previous check, make sure that the contents of the repository file follow the required structure.
For more details on the OSGi Bundle Repository, have a look at Chapter 6,Using the OSGi Bundle Repository.
If your browser requires a proxy to access the internet, then so will the Bundle Repository Service. You need to provide the proxy configuration to the framework. This can either be done as a command-line directive using -D<prop>=<value>
entries in the startup script, or in the system.properties
file under the conf
directory.
The following are the property names that are used for proxy configuration:
Check the Felix online configuration documentation for more details on this.
I'm trying to start my web application bundle, but I get error messages about JSP support not being enabled, like:
2010.06.22 19:10:12 ERROR - Bundle:com.packtpub.felix.bookshelf-webapp -
[ERROR] com.packtpub.felix.bookshelf.webapp.Activator :
[com.packtpub.felix.bookshelf.webapp.Activator-0]
The callback method validate has thrown an exception : Jsp support is not enabled. Is org.ops4j.pax.web.jsp bundle installed? -
java.lang.UnsupportedOperationException: Jsp support is not enabled. Is org.ops4j.pax.web.jsp bundle installed?
Check if the JSP extension for your selected Web Container implementation is installed. If you're using Pax Web, then refer to Chapter 13 for the installation procedure.
I've written a JSP which imports a class that's in another bundle. The bundle with that class is correctly installed on the framework, but my JSP is failing to compile; there's an error saying that this class cannot be resolved to a type.
For example, here I have a JSP (index.jsp
) that imports the class test.example.ExternalClass:
<%@ page import="test.example.ExternalClass"%>
When attempting to access that JSP in a browser, after starting the web application bundle, I get the error message:
Problem accessing /test/index.jsp. Reason:
Unable to compile class for JSP:
An error occurred at line: 11 in the jsp file: /test/index.jsp
ExternalClass cannot be resolved to a type
Mainly, there are two potential reasons for this situation.
Make sure that the bundle that's supposed to provide the class (here ExternalClass)
properly exports its package. The framework will only make classes in exported packages available for other bundles.
To rule this potential root cause out, double-check the Export-Package
manifest entry in the bundle, that provides this class. It must include the package that contains the class ExternalClass
.
If you're using the maven-bundle-plugin
to generate the OSGi manifest entries, it will look for the packages to include in the Import-Package
manifest entry by inspecting the Java sources. However, it will not look into JSPs to include the packages they import.
The packages required by JSP files need to be specified to be included as part of the Import-Package
manifest entry.
This is done in the plugin
configuration section of the project POM:
<build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <configuration> <instructions> <!-- ... --> <Import-Package>test.example,* </Import-Package> </instructions> </configuration> </plugin> </plugins> </build>
Notice that the package entry is followed by "*". This requests the plugin to also include the other detected packages along with this manually included one.
Review Chapter 13 for the steps needed for the implementation of a web application bundle.
If you're not using an automated way to construct the Import-Package
entry, then just make sure to include the required packages when setting it.