Debugging any application can be a pain in the backside and OSGi is no exception. In this article, I show you some tips on how to debug an OSGi application using Eclipse Virgo and run through a more complicated uses-conflict example in a Spring MVC, JSF, Apache CXF Web Application.
In these examples, I am using Virgo 3.0.0.M05.
Enable the Equinox Shell in Virgo
By default, the Equinox shell is disabled in Virgo (due to security reasons I suspect). Edit lines 51 and 52 to enable the shell. I’ve changed the port to 2402 as it conflicts with my local CVS:
# osgi console support osgi.console=2402
You will need to restart Virgo for this to take effect. You can then hop into the console by telneting into localhost on 2402:
telnet localhost 2402
Now that you’re in, have a play around. Starting with the ‘help’ command is a good idea. See the Virgo User Guide for more info on setting up the shell.
Look at the bundle Manifest headers, as seen by Virgo
Sometimes your manifest may not behave as you think, and is often the cause of issues. You can easily check the headers of your bundle by issuing the following:
ss headers 120
The first command lists all bundles and their states, the second allows you to view the headers associated with that bundle.
Find out importers and exporters of a package
Using this command, you can see the exporter of a particular package and version, as well as the bundles (indented) that import that package. This is really handy when you’re trying to work out why a particular package is not wiring to a bundle, or if it’s wiring to the wrong bundle in a uses-conflict.
Examine a bundle \ service in detail
Virgo provides a number of extra commands on top of the Equinox console, one of which I find particularly useful to see if my bundle and osgi contexts (module-context.xml and osgi-context.xml files respectively) have been correctly read by Virgo:
vsh bundle examine 121 vsh service examine 200
As you can see below, when you examine a bundle you are provided with a listing of all of the packages (and their versions) that are imported\exported and the services it publishes\consumes. In this case, my bundle is exporting a service with id 200 which i can examine with the second command. This allows me to confirm that a) my service is being exposed as I expected and b) it is of the correct class – it even gives me the Spring Bean name…
Find out what packages import\export a particular class
clhas com.melbourneit.web.provisioning.ProvisioningManager clload com.melbourneit.web.provisioning.ProvisioningManager clexport com.melbourneit.web.provisioning.ProvisioningManager
Useful commands to work out where are class is located and what other bundles try and load that particular class.
Diagnosing a Uses Violation – Spring MVC, Apache CXF, EHCache and JSF
These pesky problems are really annoying to fix. Neil Bartlett and Glyn Normington have explained what these are in detail, I’m going to show you how you might diagnose them using the Eclipse Virgo and Equinox console commands.
The application in question is a Spring MVC project, that uses the Apache CXF client SOAP\RESTful service communications, JSF for some presentation and uses EHCache and Terracotta for L2 caching. It also takes advantage of JSR-303 validations using the Hibernate RI. The application is multi-layered on a technical level and as you can see has a few moving parts.
So, I have a Web Application with multiple bundle dependencies, each with their own dependencies and so on. It is a typical situation that leads to a Uses Violation, so it was only a matter of time before I was confronted with the following:
The first step in the debugging process is to find the package that is to blame, that is, the package that has multiple exporters. As Neil points out “This is a necessary precondition for a uses constraint violation”. Unfortunately this is often the hardest part. So the above log snippet gives a few hints, but is particularly unhelpful: one of the following packages has a dependency on another package which has been exported at least twice: org.hibernate.validator.xml, org.springframework.remoting.jaxws, com.melbourneit.web.provisioning.
The issue is, you can’t use the console to assess what packages any of those bundles import at this point because the application has been rejected by the OSGi framework. You could manually install those bundles but it won’t re-create the set of conditions you need. Enter the State Inspector. Glyn teases us with his overview, but I think he under sells it’s value. Let me try and sell it by demonstrating its usefulness.
You need to use the Admin application that comes packaged with Virgo, so ensure that the 3 artifacts below are installed or in the pickup directory:
mfellows /usr/local/virgo5/pickup $ ll total 288 [email protected] 1 mattfellows staff 95K 27 May 16:04 org.eclipse.virgo.apps.splash-3.0.0.M05.jar [email protected] 1 mattfellows staff 658B 27 May 16:04 org.eclipse.virgo.apps.admin-3.0.0.M05.plan [email protected] 1 mattfellows staff 42K 27 May 16:05 org.eclipse.virgo.apps.repository-3.0.0.M05.par
and navigate to http://localhost:8080/admin once it loads. Once in, click on the “OSGi State” menu item in the top menu.
Notice how there is the message “Viewing state ‘Live'” at the top right-hand of the screen? Click on the select box next to it and choose the item underneath ‘live’ and hit ‘go’. In this instance, the item is ‘2011-06-18-12-47-096′ which references the dump created when the OSGi framework was unable to resolve the Web Application. Once I’ve chosen this, I now get a a snapshot of that point in time in the OSGi framework:
So, as I mentioned earlier, I can now browse around at the 3 bundles from before to see what packages might be the cause. Starting with Hibernate, I need to see what packages it imports. I now click on the hibernate link (com.springsource.org.hibernate.validator) to see what packages it imports/exports:
javax.persistance is an optional import which hasn’t been provided, so I choose javax.validation instead to see it’s exporters:
Unfortunately, it only has one exporter (com.springsource.javax.validation). How about javax.xml.bind?
Bingo! It turns out that this package has two exporters; bundle 0 providing version 0.0.0 of the package (org.eclipse.osgi), and bundle 57 (com.springsource.javax.xml.bind) providing the correct version of 2.2.0, the version Hibernate is currently wired to. Now, here is the tricky part. We know that it has two exporters, but that doesn’t mean that this IS the problem – we need to confirm that another bundle in the same classpath uses the other exported package. i.e. We need to find another bundle using the javax.xml.bind package provided by bundle 0.
Actually, with the Dump Inspector it turns out not to be that difficult. Notice how some bundles have low Bundle Id’s i.e < 500? These bundles have been resolved and are not part of the uses-conflict. Bundles with really high Bundle Id’s have not actually been resolved yet – as Glyn puts it, Virgo is attempting resolution in a “side state”, and will only be committed to the framework if resolved. So, the hint here is to look for bundles with enormous bundle id’s and see what packages they are trying to import.
On the javax.xml.bind OSGi state page, you can see that 6 bundles are importing this package but, funnily enough, only 2 packages have really high bundle id’s: Hibernate and the Web Application. Unfortunately, in my case clicking on the Web Application bundle does not reveal the provider of the javax.xml.bind package however I happen to know that bundle 0 is imported into a Web Application bundle by default if the ‘Web-ContextPath’ header is provided, which binds it to a conflicting version of javax.xml.bind. Removing this header removes the uses-conflict.
In my case, because my Web Application was tied to bundle 0, I actually needed to prevent bundle 0 from exporting the packages I needed from another bundle. I needed to modify the lib/java6-server.profile and remove the following lines:
javax.xml.bind,\ javax.xml.bind;version="2.0",\ javax.xml.bind.annotation,\ javax.xml.bind.annotation;version="2.0",\ javax.xml.bind.annotation.adapters,\ javax.xml.bind.annotation.adapters;version="2.0",\ javax.xml.bind.attachment,\ javax.xml.bind.attachment;version="2.0",\ javax.xml.bind.helpers,\ javax.xml.bind.helpers;version="2.0",\ javax.xml.bind.util,\ javax.xml.bind.util;version="2.0",\
javax.xml.ws,\ javax.xml.ws;version="2.1.1",\ javax.xml.ws.handler,\ javax.xml.ws.handler;version="2.1.1",\ javax.xml.ws.handler.soap,\ javax.xml.ws.handler.soap;version="2.1.1",\ javax.xml.ws.http,\ javax.xml.ws.http;version="2.1.1",\ javax.xml.ws.soap,\ javax.xml.ws.soap;version="2.1.1",\ javax.xml.ws.spi,\ javax.xml.ws.spi;version="2.1.1",\
These packages are provided by other bundles at runtime (springsource.javax.xml.bind, genonimo etc.). This is not a recommended thing to do, however was required in my particular circumstance. See this forum post for more details.
OSGi State Inspector Summary
To sum up, the OSGi state inspector allows you to:
- View a snapshot of the state of Virgo when a bundle fails resolution
- Browse the bundles in that snapshot and view their properties; import, export and services
- Diagnose uses-conflicts and other OSGi issues much more easily
Read more about it at the Virgo Docs.
Do you have any tips\tricks you’d like to add? Let me know!