Wednesday, April 13, 2011

Multiple Bundles per Project

I just got back from a very successful JAX London, these are always very well organized conferences and this conference was no exception. Yesterday we had an OSGi day during which Neil Bartlett succeeded in writing a Vaadin Web application without having to restart the application OSGi framework. OSGi is well on its way to provide a development process with much shorter turn around time than any other environment I know. All because of its dynamic model, there is just no need to restart the framework even if you make very big changes in your code, even your bundle layout can change or the run environment.

During this presentation someone in the audience asked why bndtools supported multiple bundles per project because all other environments (like Maven, PDE, etc) limit a project to a single artifact. So why does bndtools have multiple bundles per project? There are several reasons and I think it is interesting to highlight them.

The first reason is practical. In the OSGi build for the Reference Implementation and Compliance Tests has over 1300 bundles, mostly test bundles. Having to maintain that many projects would be very painful. In reality we now have only around 130 projects. I shudder what it would mean to have 1300 projects in your Package Explorer ...

The second reason is cohesion. Sometimes your deliverable consists of multiple bundles that are actually quite cohesive. For example, assume there is a bundle that is useful on its own but someone wants to use it in conjunction with Spring. To support that use case, your bundle then requires an import of a Spring package, which would transitively drag in many other packages. You could make this import optional but that is awkward. The best solution would be to create two bundles, one with,  and one without Spring. You could even make them a main bundle and a fragment for the Spring dependency. Being forced to put these two bundles in different projects creates an artificial separation that unnecessarily complicates development.

Last but not least, when we begin, we rarely know where the module boundaries are optimal. In bndtools an extra bundle has no overhead. It is easy to move packages between bundles or even allow them to live in multiple bundles. Experimenting with splitting a bundle or combining, or even just creating a test bundle, has no associated costs. In my experience, this changes the way you think about bundles, the process of developing them becomes more fluid. I rarely have projects that produces a single bundle nowadays. However, if you prefer a single bundle per project then that is your choice, 1:1 is the easy case.

That said, I actually never understood why popular build tools are constrained to a single output per project. Isn't that a little bit too much convention over configuration?

Peter Kriens


P.S. Ok, ok, Neil's Eclipse instance crashed because it ran out of heap space killing the application framework as well. So he almost reached perfection. :-)

16 comments:

  1. Back in the days of the IBM SMF tooling we had multiple bundles per Eclipse project, but when PDE started supporting bundles, that went away. By Eclipse 3.2 there was just too much tooling and experience based on the 1:1 approach to win that battle. But nevertheless we fought hard and lost.

    I believe that the biggest negative of the 1:1 approach is bigger and less cohesive bundles. They're also probably more tightly coupled. And anyone that knows me will tell you how much I argue for loose coupling and high cohesion. Isn't that software development 101? Well it was when I was at school.

    ReplyDelete
  2. Trouble with multiple bundles per project is that everything else in Eclipse centers on project as the smallest scope of configuration. For instance, different bundles have different classpaths, but you cannot have more than one classpath per Java project. So if you are writing multiple bundles in the same project, JDT is unable to help you as well as it usually can in keeping your code straight. Same applies to builders, natures, etc. So while you might get some benefits out of having multiple bundles per project, you are also loosing a good bit of functionality. This is why WTP has abandoned multiple modules per project idea that we experimented with in the 0.7 release many years ago.

    ReplyDelete
  3. @Konstantin: Hmm, bndtools is based on JDT and clearly does not suffer of any of the issues you raise. I guess the difference is that the last phase is managed by bnd, all other builders have already done their magic then.

    In bndtools a project defines the classpath (-buildpath) that is then shared between the bundles. This is ok between bundles in the same project should be cohesive.

    Anyway, the nice thing with 1:n is that anyone can make the tradeoff because 1:1 is a subset.

    ReplyDelete
  4. @ Simon: I agree that forcing a 1:1 approach creates a barrier to make smaller and more cohesive bundles, and vice versa. A real pity you lost the battle ...

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
  6. Gradle is a popular build tool that doesn't have artificial limitations like a single artifact per project. We also have an OSGi plugin that's based on bnd.

    ReplyDelete
  7. I'd love to see multiple bundles from the Felix maven-bundle-plugin (probably utilizing the classifier), in addition to the fragments example, a more common occurrence for me would be split interface from implementation.

    ReplyDelete
  8. @Peter: Yes, in the SMF tooling a single Eclipse project would have a single compile-time build path against which JDT would compile all the code.

    Each source folder was a module that had its own META-INF/MANIFEST.MF; the SMF tooling would read the Import-Package and Export-Package manifest headers and use those to validate that the bundle, while compiling clean, was not violating the OSGi runtime package viability rules.

    In addition, the SMF tooling could calculate your Import-Package headers by analyzing the compiled code, with help from JDT of course.

    So yes, we had multiple bundles per project, but they were always closely related bundles that shared a common compile-time classpath.

    There were also ways to compose multiple bundles from the code compiled by one or more other projects, through the use of some SMF-specific meta-data. This was helpful when you had a utility class that you wanted to put in multiple bundles yet only maintain a single copy of the source.

    ReplyDelete
  9. @earcam: The bundle plugin uses bnd. You could try to do <_sub>*.bnd in your pom, that "might" build any bnd file in the pom directory ... never tried it though.

    @Peter: I'd like a replacement for ant in the bndtools setup, or at least an alternative. Willing to work together?

    ReplyDelete
  10. Vaadin, yet another Web Framework.
    Seems a bit like GWT at first sight.

    Interesting, but so far I haven't heard of it.

    ReplyDelete
  11. "I shudder what it would mean to have 1300 projects in your Package Explorer"

    You could use Working Sets ;-)...

    ReplyDelete
  12. @Werner: Vaadin is based on GWT; it uses GWT widgets but does the logic all on the server side. Pretty cool concept.

    @mrp: :-) try maintaining sets for 1300 projects ... 1300 is a LOT

    ReplyDelete
  13. @Peter: At the moment with bndtools the set is the project and the bundles the *.bnd files, right? So this is no difference, it's just a different level of abstraction. It's managing 1300 bundles with Projects instead of Working Sets.

    Couldn't the bnd.bnd be placed in the working set configuration? Of course there would need to be some more improvements in the working set level for bndtools (View etc.). But however the Eclipse project<->bundle mapping would not be broken.

    Eclipse OSGi edition -> without "new Project", just "new Bundle"...but still compatible with Eclipse Plug-Ins.

    Just an idea, I'm not that into Eclipse to know if it's really possible. Please correct me if I'm wrong with bndtools, I have only tested it.

    Martin

    ReplyDelete
  14. @mrp: A project in Eclipse has:

    1) .classpath
    2) .project
    3) bin directory with its subdirectories
    4) src directory with its subdirectories
    5) Lots of internal data related to a project
    6) build.xml

    So 1200 times at least 30 file entries is 36.000 extra files on your hard disk and a significant extra chunk of memory in Eclipse ...

    In bndtools all these elements are shared because the bundles in a project are highly cohesive. Having a project per bundle forces me to accept the redundancy.

    However, if you like 1:1, bndtools works perfectly happy with that model, the nice thing of 1:1 is that it happens to be a subset of 1:n. I am just awfully happy with having multiple bundles per project because it really simplifies large builds for me.

    ReplyDelete
  15. @Peter You'r right with the 1:1 option of course and of course this seems to be well for your use case and others. But I think there are just to many Eclipse people out there...and they loved what OSGi gave them before!

    Btw. if I create e new Project in Eclipse there is just one file .project. Next to this there would be a *.bnd and src/bin folders. I did not mean plug-in project should map to OSGi bundle, just the hierarchical level of projects.

    I just wanted to introduce the option of giving working sets more facilities, as this is the next higher abstraction level. No offence!

    ReplyDelete
  16. @mrp: no offence taken, I actually always like it when people disagree :-)

    I would like working sets to have more facilities because they are currently quite painful to maintain. I'd love it if they could handle wildcards so I could say: *.impl.* should be a working set.

    ReplyDelete