Bnd workspace vs Maven vs Gradle

Introduction

As most Bnd/tools users will be aware, there are three main options for setting up your workspace to use Bnd:

  • Bnd workspace (optionally with Gradle for CI support)
  • Maven using the bnd-maven plugins
  • Gradle using the bnd Gradle plugins (without a cnf project, ie non-Bnd workspace)

I wanted to write a brief post to higlight the relative merits of each approach.

I come to this reflection as someone who has come to Bnd from the “outside”, who had prior experience of Maven and Gradle. When I first came to Bnd, Maven/Gradle integration was still maturing, and so this was an extra push for me to try and learn the Bnd workspace model. The Maven/Gradle plugins have matured significantly since then thanks to great work from the core Bndtools team, and if the plugins had been at their current level of maturity I may have baulked at the thought of learning yet another new build system. Having been forced to climb that mountain, Knowing what I know now, I think that this would have been a loss.

I would be happy/excited for others to contribute their own perspectives/experiences to this too.

Familiarity

Ranking: Maven, Gradle, Bnd workspace

This is one point where the Bnd workspace model is a clear loser to the alternatives. Most Java developers (and by extension, most Java development houses) are already familiar with Maven and/or Gradle. Learning a new build system is an obstacle for an individual developer, and a bigger obstacle again for a development team.

This is somewhat of a “pragmatic” criterion on which to compare the three layouts rather than a purely technical criterion; however pragmatism plays a significant role in any development house. It is particularly relevant when working with an established project that already uses Maven or Gradle as its build system - the inertia that needs to be overcome to change to a Bnd workspace model is probably not going to be worth it, even if the Bnd workspace model were to offer theoretical benefits. If starting a new project then the inertia is not quite so absolutely important, but still often important enough to carry the day (eg, when two of the core Bndtools team @bjhargrave and @rotty3000 started the osgi-test project, despite both knowing the Bnd workspace model well, they chose to use a Maven layout).

However, there is an important caveat here: if you want to do anything other than the simplest of Bnd integrations, you cannot completely avoid learning the .bnd file format - while Gradle/Maven plugin environment offer native alternatives/sensible defaults for many of the .bnd file features, there are some bnd-specific configuration that simply cannot be avoided. So if you elect to use the plugins you may not need to learn Bnd syntax like -buildpath or repository/Bnd plugin configuration, but you will probably need to learn commands like Import-Package ,Export-Package, Private-Package, Bnd macros, package selector syntax and idiosyncrasies, etc. You also can’t avoid learning Bnd syntax when it comes to launching, because both the Gradle and Maven plugin integrations use the .bndrun format to launch applications and OSGi integration tests. Once you’ve learned these core commands, you’re quite a way toward learning everything that you need to work with a full Bnd workspace.

Ecosystem diversity

Ranking: Maven, Gradle (close second), Bnd workspace

All three build systems offer support for build plugins and code generation. So in theory they are on a level playing field.

However, the Maven ecosystem benefits from being long-established and having a diverse body of well-supported 3rd-party build plugins. Gradle’s ecosystem is also quite diverse, and what it may lack in diversity relative to Maven it makes up for by its nature as a full-featured scripting language allows you to relatively easily add custom build code (see next point).

This is another area where the Bnd workspace model clearly lags the others, and probably always will.

Build plugin ease-of-development

Ranking: Gradle, Maven, Bnd workspace (last two tied?)

Gradle, being a scripting language, really shines vs the other two here, as there is not a sharp line between the build configuration and the plugin. The build configuration language is flexible and powerful enough to allow the build script to naturally evolve to the point where it can factored into a plugin.

In contrast, the barrier to writing plugins in Maven and Bnd native is somewhat higher - there is no natural evolution path. Having not had extensive experience with either I don’t think I can meaningfully comment on which is easier/better from an architectural perspective. However, the Bnd plugin support (especially for external plugins) is relatively recently added and perhaps still maturing, while the Maven support is much more established and you are much more likely to be able to find mature tutorials to help you.

IDE integration

Ranking: Bnd workspace, Maven, Gradle

The Bnd workspace is Bnd’s “native” configuration. While (as noted above) this is the root source of many of its disadvantages, it is also the root source of many of its advantages. In particular, it is typically more advanced feature-wise than the other workspace layouts, in particular when it comes to IDE integration (assuming you’re using Eclipse…). Indeed, in most respects, the Bnd workspace model is the reference-level of IDE integration that the other workspace layouts aspire to.

The Bndtools M2E integration in Eclipse for Maven is getting quite good too - it is certainly workable, as the osgi-test project demonstrates. However, it is not quite up to the level of the native Bnd workspace integration (and I give two examples below).

On this point the Gradle IDE integration is a distant third at the moment - the BuildShip support/integration isn’t really there yet (at least, it wasn’t the last time that I checked).

When considering features that are supported by the Bnd workspace integration that are not supported by the M2E integration, my two favourite features that come to mind are::

The buildpath quickfix processor

If you have a compilation error in your source that is caused by a missing type or package on your buildpath, then this feature will look this feature will look for artifacts in your workspace that could possibly fix your problem. It is particularly adept and solving compilation issues that are caused by missing transitive dependencies which can otherwise be hard to find - ie, jars that your code does not reference directly, but which are necessary for the compiler to be able to do its job (eg, a jar containing the supertype of your direct dependency - your code may not reference it directly, but sometimes the compiler will need it in order to be able to compile your code,).

While it is technically possible that this feature could be extended to work with the M2E integration, this is not trivial and currently the feature only works for the Bnd workspace model. Ok, so as the primary author of this feature I may be a little biased, :slight_smile:, but I find this feature extremely useful.

Baselining

IDE integration for baselining errors: both the Maven and Gradle plugins have support for baselining - however, these only work if you build using Maven/Gradle. Currently, there is no IDE integration for either of them. If you’re like me and you spend most of your time building in the IDE, then you won’t notice the baselining issues until it is built from Maven/Gradle. Hopefully you’re a diligent developer and you always do a command line build before pushing into your central repository :wink:, but if you are anything like me, you forget to do this sometimes and don’t find out about your baselining problems until after you’ve pushed to GitHub and the CI has run. :blush:

Again, at some point in the future there might be better IDE integration for this for M2E/Buildship, but at the moment there isn’t.

Repository support

Ranking: Bnd workspace, Gradle, Maven

Most artifacts today are consumed from Maven-shaped repositories. If all the artifacts you need are in Maven-shaped repositories, then either of the three workspace configurations will serve equally well.

However, if you need to consume artifacts from diverse repository types - eg, P2 or OBR repositories, perhaps with Maven thrown into the mix as well - then the Bnd workspace model is really your best bet. There is no real support in Maven or Gradle (yet) for other repository types (I understand that Maven Tycho supports P2 repos, but it is also my understanding that this support is heavily tied to Tycho.)

Configuration brevity

Ranking: Bnd workspace, Gradle (close second), Maven

Once you’re familiar with it, the .bnd file format is actually nice to work with. The best thing about it is that it is concise - I think it probably has a slight edge over Gradle in this respect, but when compared with Maven’s xml-based POM format it is a significant improvement.

To be fair, a more verbose configuration file format like the POM is useful when you are first learning s build system. However, once you’ve learned it, I feel that it is much more of a hinderance than anything else.

Compare the equivalents of adding dependencies from a Maven repository in both systems:

Bnd workspace

In my build.mvn file:
org.apache.felix:org.apache.felix.framework:7.0.3

In my bnd.bnd file:
-buildpath: org.apache.felix.framework

Maven

In the <dependencyManagement> section of my parent pom:

<dependency>
  <groupId>org.apache.felix</groupId>
  <artifactId>org.apache.felix</artifactId>
  <version>7.0.3</version>
</dependency>

In the pom.xml file of my individual project:

<dependency>
  <groupId>org.apache.felix</groupId>
  <artifactId>org.apache.felix.framework</artifactId>
</dependency>

Conclusion

There’s no overall clear winner here. The answer to which is best is “it depends”. But there are some clear situations to consider one over the other:

  • If you have a well-established project that is already using Maven or Gradle, stick with what you have and use the plugins for your respective build environment.
  • If you are part of a team that doesn’t know Bnd well already, seriously consider using Maven or Gradle (depending on what you’re teams most familiar with), but don’t discount the Bnd workspace if your team is open to it and adept at picking up new things.
  • If you may need to consume artifacts from anything other than a Maven repository (not common, but happens sometimes), then seriously consider the Bnd workspace model. Consider it even more seriously if you’re starting a new project from scratch.
  • If you already have a project that uses PDE as its primary build system (perhaps with POM-less Tycho build support), seriously consider the Bnd workspace model (+Gradle CI integration).
6 Likes