So, OSGi is supposed to make it easier to isolate problems and therefore quicker to resolve. Alas, that is not the case yet – although this may yet change as I start to apply all the tools that are rapidly maturing in this space.
The problem is my application (the ‘fancyfoods’ website, from the ‘Enterprise OSG in Action’ tutorial) is failing to startup correctly, to wit:
- The servlet that displays the special offers that I know is available from the ‘fancyfoods’ store is saying there is none available.
- A number of exception errors in the console window I use to launch the OSGi application.
To date, the book has been accurate in terms of the key source code and configurations it requires. So in all probability, the error was likely due to my very novice development/test environment configuration.
So, nothing to do but pick through the exceptions and try to decipher it.
It starts with this beauty, which basically says the first operation which attempts to access the persistent store is failing (it does a count to see if any rows exist in the database):
[Blueprint Extender: 2] ERROR org.apache.aries.blueprint.container.BlueprintContainerImpl – Unable to start blueprint container for bundle fancyfoods.persistence
org.osgi.service.blueprint.container.ComponentDefinitionException: Unable to intialize bean populator
Caused by: java.lang.VerifyError: Expecting a stackmap frame at branch target 41
fancyfoods/persistence/FoodImpl.<clinit>()V @32: ifnull
Expected stackmap frame at this location.
[Blueprint Extender: 1] WARN Transaction – Error ending association for XAResource org.apache.derby.jdbc.EmbedXAResource@e5a209e; transaction will roll back. XA error code: 100
As some background, Derby is an SQL-based database written in Java that implements JPA (Java Persistence API). It is used as the reference persistence implementation service for the ‘fancyfoods’ applications, as a simple substitute for mySQL or Oracle, etc.
After spending *way* too much time trying to figure out this error and verifying the various configuration files etc were correct (and in the process understanding a whole lot more about OSGi Blueprint), it turns out that the error was quite mundane, and indeed related to my dev/test environment, which uses the Mac OS X version of Java 1.7.
The turning point was this post from stackoverflow.com:
Adding the ‘-XX:-UseSplitVerifier’ to my OSGi run script fixed the problem.
Along the way I, I investigated and eliminated all kinds of debug messages that were suggestive of problems but seemed to be relatively normal, or were just symptoms of the original error – for example, mysterious unbinding of services seemed to precede the exception being thrown. I suspect now that this was due to the multi-threaded nature of OSGi, and once the exception was thrown, various activities kicked in that displayed messages before the thread with the exception displayed its message.
Trying to solve this highlighted a few things:
- OSGi is powerful, but when services don’t work as expected, it is devilishly difficult to trace through a potentially complex web of dependencies to figure out where things have gone wrong. Blueprint in particular is a challenge: being declarative, tracing cause and effect can be non-trivial.
- Getting your dev/build environment right is soooo key..spend time on this, it is worth it, and shouldn’t change much once the basic architecture is in place.
- The ‘services’ mindshift in Java coding is quite significant: I haven’t got there yet, and I think this is at least partially because Java is basically an imperative language, and services are more declarative in nature, so it requires the two concepts to co-habitate. More sophisticated tools are needed to support this, especially in an enterprise setting.
Next up for OSGi: finish chapter 3 (implementing distributed and multipart transactions). Hopefully there won’t be any showstoppers to slow things down in the meantime..