Category Archives: Java

Bndtools Randomness

Over the past several weeks I’ve been tinkering with OSGi in my free time. My approach has been anything but systematic, rather, it’s been a sort of chaotic scrambling from one tool or problem to the next. I’ve got a loosely formed goal in mind, but I’ve been happy to take detours along the way. I started simply enough by downloading Karaf and getting some bundles deploying, tinkered with Camel and dove into building some simple case studies and test apps to get a feel for things. Eventually that work took me into Pax Exam and then Pax Runner, completely invaluable tools in learning the ropes of provisioning containers for specific purposes from the ground up.

Lately, I’ve been spending some playing with bndtools, an Eclipse plugin that kept popping up. The reason for my post is mainly to clear up some of the confusion that I myself had about how bndtools works and fits into the world of OSGi. First, I suggest you actually take one of the many tutorials that are out there. I’m not going to walk you through what others have already documented, rather, just point out some of the things that were critical to my understanding and accepting of bndtools into my development process.

Maven

I’ve actually gone from not minding Maven to hating Maven to liking Maven again. Despite the criticism it’s received it’s doing its job fantastically. At first, I thought that bndtools would require some duplication of my build (as an Ant build) or bundle metadata if I wanted to keep Maven alive in my project. Not true.  Because the bnd.bnd file is nothing more than a bnd configuration file, we can take full advantage of the UI and goodness that bndtools is providing and still use Maven. Bndtools is merely layering on some convention and Eclipse integration. Ant builds aren’t necessar, though using an Ant build can offer a little more flexibility than Maven can (i.e. sub-bundles). This made me happy as I was already using bnd as part of my Maven build. Most of what follows here is mentioned in this thread on the mailing list that I fortunately stumbled upon. The first step to getting things playing nicely is to update your maven-bundle-plugin configuration in your pom to reflect something like this:

<plugin>
  <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
      <instructions>
        <_include>bnd.bnd</_include>
      </instructions>
    </configuration>
</plugin>

This tells the plugin to read the bnd.bnd file for the configuration directly. Next, we need to update the project wide bnd settings and change some default directories:

bin: target/classes
src: src/main/java
target-dir: target/bndtools

Only the first property is actually necessary, the others don’t hurt and I do prefer my build artifacts in the target directory. Finally, in the bnd.bnd file itself you’ll need to specify the Bundle-SymbolicName and the Bundle-Version options, like so:

Bundle-SymbolicName: com.example.api
Bundle-Version: 1.0.0-SNAPSHOT

There were a few places that suggested you could use ${pom.artifactId} and ${pom.version} here if you enabled sub-bundles (via -sub: *.bnd) Enabling sub-bundles did cause those placeholders to work for me, though I ended up losing half of the useful tabs available when editing the bnd.bnd file.

After these changes, things worked great!

Web Applications

I had a few WARs that I was building and was able to get those working by moving to WABs – very easily done by adding the following lines to the respective bnd.bnd files:

wab: src/main/webapp/
Web-ContextPath: webapp

Random Tips

Bndtools is under pretty active development and things are still coming together. Here are some things I ran into that may help point others in the right direction, though I don’t imagine they will apply for much longer.

  1. Your cnf directory shoudd be immediately under the workspace directory and alongside your project directories. Some errors I was seeing that are related to this are:
    • No workspace found from <some project>
  2. Project names should match their bundle names. Some errors I was seeing that are related to this are:
    • NullPointerException’s in BsnValidator (actually a bug, once fixed you’d get a ‘Bundle-SymbolicName is not valid for builder’ message)
  3. If when you’re adding a bundle to your local repository and you get an error about a failure to rename, you’re likely using an older version of bndlib. When you upgrade the version of bndtools be sure that you also recreate the cnf directory. I hadn’t expected the bndlib version in cnf to affect the dialogs and messages I was seeing in Eclipse, but they were. I had upgraded bndtools but not changed cnf and was still seeing this error (The root cause is that the temporary Jar wasn’t being closed before being move into the repository)

Building Bndtools

I did build my own bndtools while toying with things, just to see if upgrading would fix some of the bizarre issues I had been seeing. Eventually I narrowed the problems down to others (like location of cnf, or the project names being wrong) Here are some issues I saw when getting bndtools compiled:

  • When I first tried building with Ant I got an error about Repo too few arguments. I fixed this by double checking the URLs in the repositories.bnd, specifically the repository for the bnd sources. In mine, bndBuildNum was for an older build that was no longer available on the Hudson server.  I changed this to a newer build number. Pay attention to version numbers in the Hudson builds though, newer builds will require you to change bndlib-version-base and bndlib-version-ceiling. I eventually just cloned bnd and used the localRepo option. I’m guessing that the ${repo} macro needs some better error handling of situations where files are missing or URLs are bad? Not sure.
  • I again ran into the “rename failed” problem when building the bnd distribution. I fixed that by copying the newer bndlib I had just built into the cnf/repo/biz.aQute.bnd directory and running again.

That’s all I got for now… hope that wasn’t too much and/or too scrambled. Good luck!

Type for TypedQuery incompatible with query return type.

I was playing around with an OSGi/Hibernate sample application that was using Apache Aries to provide EntityManagers to bundles and ran into a weird issue when I began querying. Take the following code:

TypedQuery<User> query = em.createQuery("FROM User", User.class);
List<User> users = query.getResultList();

At runtime, createQuery would throw “Type specified for TypedQuery [com.page5of4.ms.examples.subscriber.model.User] is incompatible with query return type [interface java.util.Map]” which was very confusing. After some digging, I discovered this code deep inside Hibernate (EntityType)

private Class determineAssociatedEntityClass() {
  try {
    return ReflectHelper.classForName(getAssociatedEntityName());
  }
  catch (ClassNotFoundException cnfe) {
    return java.util.Map.class;
  }
}

Suddenly this is a common OSGi problem. ReflectHelper.classForName does what anybody familiar with OSGi class loading peculiarities would imagine – tries to use the TCCL and then falls back on Class.forName.  This took me some time to uncover and is fairly obscure given the error I was seeing and so I figured I’d write this post to help anybody else that runs into the same issue. You can avoid the problem a few ways:

  1. Export your model packages assuming DynamicImport-Package is enabled on whatever Hibernate bundle you’re using.
  2. Use non-TypedQuery createQuery (meh)

I’m still pretty new to this OSGi stuff so if there’s a better solution I’d love to hear about it… Hope this helps somebody!