<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"> 
 <title>Neil Bartlett</title>
 <link href="/atom.xml" rel="self"/>
 <link href="/"/>
 <updated>2019-06-15T19:24:17+00:00</updated>
 <id>http://njbartlett.github.com/</id>
 <author>
   <name>Neil Bartlett</name>
   <email>njbartlett@gmail.com</email>
 </author>
 
 
   <entry>
     <title>March of the IDEs — IDE Agnostic OSGi Development</title>
     <link href="http://njbartlett.name/2017/09/16/ide-agnostic-osgi.html"/>
     <updated>2017-09-16T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2017/09/16/ide-agnostic-osgi</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;For a long time Eclipse has been, in practice, the only widely used and supported IDE for developing OSGi applications. Both of the premier IDE plugins — namely &lt;a href=&quot;http://bndtools.org/&quot;&gt;Bndtools&lt;/a&gt; and the older &lt;a href=&quot;https://www.eclipse.org/pde/&quot;&gt;PDE&lt;/a&gt; — supported only Eclipse. While some tooling existed in IntelliJ and NetBeans it was nowhere near as comprehensive or usable.&lt;/p&gt;

&lt;p&gt;This wasn’t much of a problem for me personally. I have been a fan of Eclipse since I first saw it in the early 2000s, and indeed the first IDE I ever used was VisualAge for Java, which later morphed into Eclipse. I’ve tried other IDEs but I always end up reverting to the familiar.&lt;/p&gt;

&lt;p&gt;However IDE choice is very personal, and the devotion of some developers to their preferred IDE can make religious fanatics seem positively lukewarm. So if you met an IntelliJ fan and told her that she would need to switch to Eclipse in order develop for OSGi… well, it’s unsurprising that a common response was that OSGi could get stuffed.&lt;/p&gt;

&lt;p&gt;So while I continue to use and support Bndtools in Eclipse, for the sake of OSGi adoption I have long wished for there to be a better development experience in the other popular IDEs. I’m happy to report that substantial progress has been made towards this goal. The latest version of bnd includes a suite of plugins for both Maven and Gradle that make development of OSGi applications practical irrespective of the IDE. Combined with some minimal IDE-specific tooling, such as that included in the latest IntelliJ builds, it is now a productive and even pleasurable activity.&lt;/p&gt;

&lt;p&gt;On 23 October I will present a talk at the &lt;a href=&quot;http://germany.osgiusers.org/Main/UFG2017&quot;&gt;OSGi Users Forum Germany Tooling Workshop&lt;/a&gt; titled &lt;strong&gt;March of the IDEs — IDE Agnostic OSGi Development&lt;/strong&gt;. In my talk I will demonstrate the development of a single OSGi application using Eclipse, IntelliJ, Visual Studio Code and a variety of command-line tools. This will highlight the opportunities for developers of all creeds to collaborate on high-quality modular code.&lt;/p&gt;

&lt;p&gt;The workshop takes place all day on 23 October and is located at the Forum am Schlosspark, Ludwigsburg, Germany. This is the same venue as &lt;a href=&quot;https://www.eclipsecon.org/europe2017/&quot;&gt;EclipseCon Europe and OSGi Community Event 2017&lt;/a&gt; but it is organised as a separate event. Participation is free and you do not need a ticket for EclipseCon but you do need to register with the OSGi User Forum Germany by emailing &lt;a href=&quot;mailto:germany-info@osgiusers.org&quot;&gt;germany-info@osgiusers.org&lt;/a&gt;. I hope to see you there!&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Bndtools and Maven&#58; A Brave New World</title>
     <link href="http://njbartlett.name/2017/09/13/bndtools-and-maven.html"/>
     <updated>2017-09-13T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2017/09/13/bndtools-and-maven</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;At this year’s OSGi Community Event – co-hosted with EclipseCon Europe 2017 – I will present a new tutorial titled &lt;a href=&quot;https://www.eclipsecon.org/europe2017/session/bndtools-and-maven-brave-new-world&quot;&gt;Bndtools and Maven: A Brave New World&lt;/a&gt;. My friend and &lt;a href=&quot;https://paremus.com&quot;&gt;Paremus&lt;/a&gt; colleague &lt;a href=&quot;https://blogs.paremus.com/author/tim-ward/&quot;&gt;Tim Ward&lt;/a&gt; will co-present and will provide support during the exercises.&lt;/p&gt;

&lt;p&gt;Bndtools has long provided the premier development experience for writing OSGi bundles and applications. However there was a significant gap: until recently it has been very difficult to use Maven to build Bndtools projects. This was partially because of legacy issues (after starting with ANT as our standard build tool, we eventually migrated to Gradle). Partially it was because Maven is far more prescriptive in terms of the structure and lifecycle of a project, and it took a long time to find a way to fit our models together. These problems meant that Bndtools was simply unusable for a large number of developers, in particular those working for organisations that have standardised on Maven – and also of course those developers who simply prefer Maven!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;These problems are now essentially solved and, from Bndtools version 3.4, Maven is a fully supported build environment.&lt;/strong&gt; Gradle also remains fully supported.&lt;/p&gt;

&lt;p&gt;In this tutorial, we will walk through all of the day-to-day development tasks in the new Bndtools/Maven toolchain. These include:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Starting a new project from scratch;&lt;/li&gt;
  &lt;li&gt;Adding bundle modules to the project;&lt;/li&gt;
  &lt;li&gt;Managing library dependencies;&lt;/li&gt;
  &lt;li&gt;Integration testing (i.e. in-container testing);&lt;/li&gt;
  &lt;li&gt;Running bundles and tests from the IDE, and the rapid code/run cycle enabled by Bndtools;&lt;/li&gt;
  &lt;li&gt;Indexing, resolving and assembling applications for deployment;&lt;/li&gt;
  &lt;li&gt;Managing bundle and package versions;&lt;/li&gt;
  &lt;li&gt;Configuring a Continuous Integration build.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following Maven plugins will be covered:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;bnd-maven-plugin&lt;/code&gt;: the core plugin that generates OSGi bundle JARs;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;bnd-testing-maven-plugin&lt;/code&gt;: executes OSGi in-container tests;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;bnd-indexer-maven-plugin&lt;/code&gt;: indexes OSGi bundles and dependencies for assembly and/or runtime resolving;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;bnd-export-maven-plugin&lt;/code&gt;: assembles a standalone OSGi application from its minimal bundles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We do hope that you will attend this tutorial armed with lots of questions! Prerequisites are Bndtools 3.5 (which will have been released before the conference), JDK 8 and Maven 3. Also make sure you sign up to attend the tutorial on the EclipseCon website, and of course you also need a ticket to the main conference.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Using Let's Encrypt Certificates with OSGi HTTP Service</title>
     <link href="http://njbartlett.name/2016/06/07/letsencrypt-osgi.html"/>
     <updated>2016-06-07T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2016/06/07/letsencrypt-osgi</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Rather than one of my usual polemics, this is a quickly-written practical post. I hope the information here is useful to somebody.&lt;/p&gt;

&lt;p&gt;Currently I am setting up &lt;a href=&quot;https://effectiveosgi.com/&quot;&gt;effectiveosgi.com&lt;/a&gt;, the website for my upcoming book “Effective OSGi”. The site is a web app that will allow users to download preview PDFs, order print copies, and so on. Naturally I am developing it in Java and OSGi (in fact, many of the code samples in the book are based on the application that will be used to sell and deliver it).&lt;/p&gt;

&lt;p&gt;Of course I want to follow best practices and use TLS (HTTPS), and this is much easier nowadays thanks to &lt;a href=&quot;https://letsencrypt.org&quot;&gt;Let’s Encrypt&lt;/a&gt;. However, it wasn’t exactly obvious how to import the certicate provided by Let’s Encrypt into a Java/OSGi application, so I’m documenting the steps that worked for me.&lt;/p&gt;

&lt;h3 id=&quot;step-one-get-the-certificate&quot;&gt;Step One: Get the Certificate&lt;/h3&gt;

&lt;p&gt;This part I’m not going document in detail because it’s more than adequately documented on the &lt;a href=&quot;https://letsencrypt.org/getting-started/&quot;&gt;Let’s Encrypt - Getting Started&lt;/a&gt; page. I used the “standalone” method. The subsequent steps assume that you have successfully obtained your certificate files, which will be saved under the path &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/letsencrypt/live/[yourdomain]&lt;/code&gt;. The files you will find there are &lt;code class=&quot;highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;chain.pem&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;fullchain.pem&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;privkey.pem&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;step-two-build-java-keystore&quot;&gt;Step Two: Build Java Keystore&lt;/h3&gt;

&lt;p&gt;Note that this step is relevant for all Java developers, not just OSGi users.&lt;/p&gt;

&lt;p&gt;Java applications cannot directly read PEM files; we need to generate a Java keystore file using the &lt;code class=&quot;highlighter-rouge&quot;&gt;keytool&lt;/code&gt; program included with the JDK. Unfortunately &lt;code class=&quot;highlighter-rouge&quot;&gt;keytool&lt;/code&gt; also can’t read PEM files directly, so we first have to use &lt;code class=&quot;highlighter-rouge&quot;&gt;openssl&lt;/code&gt; to convert them to PKCS12 format:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem \
        -out cert_and_key.pkcs12 -name MyDomain \
        -CAfile chain.pem -caname root
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You will be prompted to enter an export password. This will only be used in the next step, so it’s fine to use just &lt;code class=&quot;highlighter-rouge&quot;&gt;password&lt;/code&gt;. Now we have a file called &lt;code class=&quot;highlighter-rouge&quot;&gt;cert_and_key.pkcs12&lt;/code&gt; which combines both the full certificate chain with the private signing key. Import this into a new keystore file as follows:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;keytool -importkeystore \
        -srckeystore cert_and_key.pkcs12 -srcstoretype PKCS12 -srcstorepass password \
        -destkeystore letsencrypt.jks -deststorepass XXXXXX -destkeypass XXXXXXX
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You now have a keystore file named &lt;code class=&quot;highlighter-rouge&quot;&gt;letsencrypt.jks&lt;/code&gt;. Keep the store and key passwords safe and secret!&lt;/p&gt;

&lt;h3 id=&quot;step-three-configure-http-service&quot;&gt;Step Three: Configure HTTP Service&lt;/h3&gt;

&lt;p&gt;This step is relevant to OSGi developers. I’ll assume you are using the &lt;a href=&quot;https://felix.apache.org/documentation/subprojects/apache-felix-http-service.html&quot;&gt;Apache Felix HTTP Service&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The HTTP Service is configured with the standard OSGi Configuration Admin. You need to create a configuration record with a PID of &lt;code class=&quot;highlighter-rouge&quot;&gt;org.apache.felix.http&lt;/code&gt; with the following settings:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;org.apache.felix.https.enable true
org.osgi.service.http.port.secure: 8443
org.apache.felix.https.keystore: path/to/letsencrypt.jks
org.apache.felix.https.keystore.password: XXXXXX
org.apache.felix.https.keystore.key.password: XXXXXXX
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This should be all you need to do get a green lock icon in your browser. Congratulations, you are now running a properly configured HTTPS server!&lt;/p&gt;

&lt;p&gt;However… it’s not very secure yet. Once your site is running, I &lt;strong&gt;strongly&lt;/strong&gt; recommend testing your TLS implementation using &lt;a href=&quot;https://www.ssllabs.com/ssltest/&quot;&gt;SSL Labs from Qualys&lt;/a&gt;. If you do this now, you will get at best a B grade.&lt;/p&gt;

&lt;h3 id=&quot;step-four-getting-the-a-grade&quot;&gt;Step Four: Getting the A Grade&lt;/h3&gt;

&lt;p&gt;One of the security warnings reported by SSL Labs is due to &lt;a href=&quot;https://weakdh.org&quot;&gt;weak Diffie-Hellman groups&lt;/a&gt;. I don’t pretend to understand everything on the linked page, but fortunately the fix is easy: you just need to make sure your Java VM uses 2048-bit Diffie-Hellman keys by setting a system property. This can be specified on the command line as follows:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;java -Djdk.tls.ephemeralDHKeySize=2048 ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To achieve &lt;a href=&quot;https://blog.qualys.com/ssllabs/2013/06/25/ssl-labs-deploying-forward-secrecy&quot;&gt;forward secrecy&lt;/a&gt; you also need to restrict the cipher suites to use only elliptic-curve algorithms. It’s also a good idea to limit the server to 256-bit rather than 128-bit algos. This is done in the configuration admin record for the HTTP Service; just add the following:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;org.apache.felix.https.jetty.ciphersuites.included: \
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, \
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, \
    TLS_RSA_WITH_AES_256_CBC_SHA256, \
    TLS_RSA_WITH_AES_256_CBC_SHA
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With these settings you should now be a grade A student:&lt;/p&gt;

&lt;p&gt;&lt;img width=&quot;600&quot; src=&quot;/images/posts/ssl-grade-a.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Finally: you might be wondering how to get an elusive A+ grade on SSL Labs. Alas it doesn’t currently seem to be possible in a Java-based server (though I may be wrong – please let me know in the comments). The feature needed to unlock A+ is called &lt;a href=&quot;https://datatracker.ietf.org/doc/rfc7507/&quot;&gt;TLS_FALLBACK_SCSV&lt;/a&gt;, and it requires an &lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8061798&quot;&gt;API change&lt;/a&gt;. Hopefully it will be implemented in Java 9.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Vertical Components</title>
     <link href="http://njbartlett.name/2016/05/06/vertical-components.html"/>
     <updated>2016-05-06T10:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2016/05/06/vertical-components</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;h3 id=&quot;combining-web-and-osgi-components&quot;&gt;Combining Web and OSGi Components&lt;/h3&gt;

&lt;p&gt;I consider myself a latecomer to Microservices; I only really started to understand and use them in 2005. Nobody called them “Microservices” at the time – as far as I can tell, the term was coined in 2006 by BEA for their &lt;a href=&quot;https://web.archive.org/web/20061017101304/http://www.bea.com/framework.jsp?CNT=msa.jsp&amp;amp;FP=/content&quot;&gt;microService Architecture (mSA)&lt;/a&gt;. Regardless, with this history it was a little surprising to hear the term reinvented in 2014 and suddenly gain a great deal of traction. While implementation details vary, the fundamental concept has not changed: small, independently deployable, discoverable services.&lt;/p&gt;

&lt;p&gt;I’m always keen to hear from people with a different take, and so in 2014 I found myself listening to a &lt;a href=&quot;http://www.se-radio.net/2014/09/episode-210-stefan-tilkov-on-architecture-and-micro-services/&quot;&gt;Software Engineering Radio podcast interview with Stefan Tilkov&lt;/a&gt;, an expert on REST and software architecture, on the subject of microservices. One of his ideas as elaborated on the podcast was to use microservices to slice applications vertically, rather than the horizontal layering that is much more commonly seen in enterprise architectures. He promotes the idea of a &lt;em&gt;Self-Contained System&lt;/em&gt; that includes all of the logic, data and UI for a single business domain. Inclusion of the UI is what makes the approach unconventional: componentisation is relatively commonplace in the back-end, but does not often extend all the way up to the user. This is a fine idea, as it allows technical teams to align with business units. When building horizontal layers (data access layers, application servers, ESBs, etc) developers easily get sidetracked into endlessly polishing frameworks rather than delivering real business value.&lt;/p&gt;

&lt;p&gt;The problem was, at least as I saw things at the time, that the UI tier was hard to componentise in this way. The web is by far the dominant UI platform, but web modularity has historically been difficult. The traditional unit of deployment and isolation in the web is the HTML page, but in a modern web application the page is the whole application. Frameworks like Angular and React help in wiring together single-page applications, but didn’t really allow applications to be composed out of independently deployable components. Also, crucially, code written for Angular is useless in a React app and &lt;em&gt;vice versa&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Of course, I was missing the &lt;a href=&quot;http://webcomponents.org&quot;&gt;Web Components&lt;/a&gt; family of specifications. In my defence, I don’t think many people knew about Web Components, as all the noise seemed to be around the competing frameworks. Also they were not really practical until recently due to the lack of support in browsers. As I write this in mid-2016, however, things have moved forward and Web Components seem to finally be ready for production. This means we can now write independently deployable and reusable components that can be assembled into an application. There are various libraries for building components, but the specifications allow (theoretically!) for components to interoperate irrespective of their implementation details. The application developer can still use a framework to assemble these components into a complete application.&lt;/p&gt;

&lt;p&gt;The parallels with OSGi components are very clear. So I started thinking about whether we can combine the two worlds to define &lt;em&gt;vertical components&lt;/em&gt;. A web component is often required to invoke logic or retrieve data from a back-end server, which creates a coupling. So what if we could create an artifact that deploys both the front-end and the back-end components together? And then what if we could use the OSGi Resolver to assemble an application out of its required UI and back-end components? So that’s what I have experimented with, and the results seem quite encouraging.&lt;/p&gt;

&lt;p&gt;I have shared a &lt;a href=&quot;https://github.com/njbartlett/demo-vertical-components&quot;&gt;proof-of-concept on GitHub&lt;/a&gt;, which implements a very simple Shopping Cart component that displays the content of the customer’s cart, retrieved from a back-end REST service.&lt;/p&gt;

&lt;h3 id=&quot;web-component-code&quot;&gt;Web Component Code&lt;/h3&gt;

&lt;p&gt;I have tried to use as few libraries and assistive technologies as possible, in order to show that nothing magical is happening. So, while libraries like &lt;a href=&quot;https://www.polymer-project.org/1.0/&quot;&gt;Polymer&lt;/a&gt; or &lt;a href=&quot;https://bosonic.github.io&quot;&gt;Bosonic&lt;/a&gt; are handy for creating web components, it’s also pretty easy to define a simple component in plain vanilla ES2015:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`
    &amp;lt;div class=&quot;cart-list&quot;&amp;gt;
      &amp;lt;h2&amp;gt;Cart Contents:&amp;lt;/h2&amp;gt;
      &amp;lt;table class=&quot;items-table&quot;&amp;gt;&amp;lt;/table&amp;gt;
    &amp;lt;/div&amp;gt;
  `&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CartListWidget&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;HTMLElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;createdCallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createShadowRoot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerHTML&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shadowRoot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'.items-table'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;requestServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;requestServer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;that&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;XMLHttpRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

      &lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'GET'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'/cart-list/servlet/'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;onload&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;responseText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sku&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;'&lt;/span&gt;
                  &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;rows&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;that&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerHTML&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;xhr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;registerElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cart-list'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;CartListWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;osgi-component-code&quot;&gt;OSGi Component Code&lt;/h3&gt;

&lt;p&gt;The JavaScript file is served from an OSGi bundle that also provides the REST service. I could have used JAX-RS for this, but a plain old Servlet works just as well for such a small demo. I even build the JSON response with printf!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;property&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;HTTP_WHITEBOARD_SERVLET_PATTERN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;=/cart-list/servlet/*&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;HTTP_WHITEBOARD_RESOURCE_PATTERN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;=/cart-list/*&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;HTTP_WHITEBOARD_RESOURCE_PREFIX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;=/cart-list&quot;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@WebComponent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;cart-list&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@RequireHttpImplementation&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CartServlet&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpServlet&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Servlet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;long&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serialVersionUID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1L&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;nd&quot;&gt;@Reference&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CartManager&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doGet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpServletRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpServletResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                                        &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IOException&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PrintStream&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PrintStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getOutputStream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;Cart&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getCart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;anonymous&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;StringBuilder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StringBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;[&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CartEntry&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;listEntries&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{\&quot;sku\&quot; : \&quot;%s\&quot;, \&quot;price\&quot; : %d}&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSku&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSoldPrice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()));&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;]&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ServletException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;application-code&quot;&gt;Application Code&lt;/h3&gt;

&lt;p&gt;Finally, the application bundle contains &lt;code class=&quot;highlighter-rouge&quot;&gt;index.html&lt;/code&gt; which simply uses the &lt;code class=&quot;highlighter-rouge&quot;&gt;cart-list&lt;/code&gt; component we defined:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;en&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Bookstore App&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;webcomponents.min.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/cart-list/component.js&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Book Store&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;cart-list&amp;gt;&amp;lt;/cart-list&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h3 id=&quot;resolution&quot;&gt;Resolution&lt;/h3&gt;

&lt;p&gt;In the code there are a couple of new annotations, which I have adapted from &lt;a href=&quot;http://enroute.osgi.org&quot;&gt;OSGi en Route&lt;/a&gt;. In the web component bundle, the &lt;code class=&quot;highlighter-rouge&quot;&gt;@WebComponent&lt;/code&gt; annotation generates a &lt;code class=&quot;highlighter-rouge&quot;&gt;Provide-Capability&lt;/code&gt; header in the OSGi bundle manifest that declares our bundle provides the &lt;code class=&quot;highlighter-rouge&quot;&gt;cart-list&lt;/code&gt; web component. The &lt;code class=&quot;highlighter-rouge&quot;&gt;@RequireHttpImplementation&lt;/code&gt; generates a requirement for an HTTP Service implementation.&lt;/p&gt;

&lt;p&gt;In the application bundle we use &lt;code class=&quot;highlighter-rouge&quot;&gt;@RequireWebComponent&lt;/code&gt; to require the component that is provided by the web-component bundle. The application bundle also repeats the &lt;code class=&quot;highlighter-rouge&quot;&gt;@RequireHttpImplementation&lt;/code&gt; annotation for completeness.&lt;/p&gt;

&lt;p&gt;These annotations are used by an OSGi Resolver, such as the build-time resolver in &lt;a href=&quot;http://bndtools.org/&quot;&gt;Bndtools&lt;/a&gt; or the runtime resolver in &lt;a href=&quot;https://paremus.com/products/&quot;&gt;Paremus Service Fabric&lt;/a&gt;. Because of this, we don’t need to manually list all of the components and libraries used by the application… we only need to list the top-level bundle (in this case &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.webapp.bookstore&lt;/code&gt; which contains the &lt;code class=&quot;highlighter-rouge&quot;&gt;index.html&lt;/code&gt;) and the tooling will automatically pull in the &lt;code class=&quot;highlighter-rouge&quot;&gt;cart-list&lt;/code&gt; component bundle along with an HTTP Service implementation such as Jetty.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;This is just a proof-of-concept and there are many details that could be improved. For example, the mapping between the component name and the URL of the JS and Servlet could be handled by a small server-side framework. Using third-party components from Bower or NPM could be made simpler, perhaps via an extender bundle.&lt;/p&gt;

&lt;p&gt;What do you think… is this a useful approach? What flaws have I missed? Let me know in the comments, or using the contact details to the right.&lt;/p&gt;

&lt;p&gt;If you are interested in learning more about web development with OSGi, and about modern component-oriented development with Java, then please consider supporting my new book, &lt;a href=&quot;https://www.indiegogo.com/projects/effective-osgi&quot;&gt;Effective OSGi&lt;/a&gt;, or buying a copy when it is published!&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Jigsaw is a Shibboleth</title>
     <link href="http://njbartlett.name/2015/12/03/jigsaw-is-a-shibboleth.html"/>
     <updated>2015-12-03T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2015/12/03/jigsaw-is-a-shibboleth</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;It comes as no surprise that Oracle has &lt;a href=&quot;http://mail.openjdk.java.net/pipermail/jdk9-dev/2015-December/003149.html&quot;&gt;proposed to delay the release of JDK 9 for 6 months&lt;/a&gt; (but note that JSR 376 specifying the Java Platform Module System is being &lt;a href=&quot;http://mail.openjdk.java.net/pipermail/jpms-spec-observers/2015-December/000233.html&quot;&gt;delayed by a full year&lt;/a&gt;, so Java SE 9 itself will likely be delayed by at least that long).&lt;/p&gt;

&lt;p&gt;The reason for the delay will also be no surprise: Jigsaw is still not ready.&lt;/p&gt;

&lt;p&gt;The crusade to develop a new module system for Java has been long and mostly fruitless. JSR 277 “The Java Module System” began over ten years ago, in June 2005… more than a year before Java 6 was released, and five years before Oracle acquired Sun Microsystems. It was meant to be delivered in Java 7 but it slipped to Java 8. When it looked like it was going to seriously delay the release of Java 8, it slipped again to Java 9. Now the same thing is happening yet again. The tongue-in-cheek prediction made by Robert Dunne is gradually coming true:&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;All I know about Java version 20 is that Project Jigsaw will be looking good and on target for version 21 &lt;a href=&quot;http://t.co/CqHCI1nTaV&quot;&gt;http://t.co/CqHCI1nTaV&lt;/a&gt;&lt;/p&gt;&amp;mdash; Robert Dunne (@rsdunne) &lt;a href=&quot;https://twitter.com/rsdunne/status/494123207977607168&quot;&gt;July 29, 2014&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async=&quot;&quot; src=&quot;//platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;

&lt;p&gt;It really doesn’t have to be this way: Jigsaw has already achieved something extremely valuable, and Java 9 could be released on schedule with Jigsaw as it stands, in addition to the other nice features slated such as &lt;a href=&quot;http://openjdk.java.net/jeps/254&quot;&gt;compact Strings&lt;/a&gt; and &lt;a href=&quot;http://openjdk.java.net/jeps/193&quot;&gt;standard replacements for sun.misc.Unsafe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What Jigsaw has achieved is modularisation of the JDK, including the standard libraries. With the &lt;code class=&quot;highlighter-rouge&quot;&gt;jdeps&lt;/code&gt; tool that was released in Java 8, you can quite easily work out the minimal set of platform modules needed by your application, and then ship a cut-down copy of Java along with it. This will be invaluable for desktop and mobile apps, and for Java’s viability in the burgeoning IoT market.&lt;/p&gt;

&lt;p&gt;What Jigsaw has not yet achieved – and frankly seems to be as far off as ever – is delivering a practical module system for applications. There are huge question marks over whether the uncompromising inflexibility of Jigsaw can ever work for Java EE, or Spring, or CDI, or Hibernate, or dynamic languages like Groovy and JavaScript. This much is apparent to anybody browsing the mailing lists. Unfortunately Oracle is holding up the release of the modularised JDK while they try to figure out all of the application-level problems.&lt;/p&gt;

&lt;p&gt;Worse, Jigsaw is already quite complex and will only grow in complexity as it is forced to support code patterns that are widely used in the Java ecosystem. Jigsaw is repeatedly touted as a “simple” module system… simpler than OSGi, which is perceived as complex. But OSGi did not set out to be complex: it is only as complex as it needs to be in order to work in the messy real world. When Jigsaw reaches a comparable level of complexity, what will be the excuse for choosing it over OSGi?&lt;/p&gt;

&lt;p&gt;OSGi is &lt;em&gt;clearly&lt;/em&gt; a better module system for applications. It is dynamic, it has a powerful service registry, and has a dependency model that makes sense and is amenable to automated reasoning. As I proved in my &lt;a href=&quot;/2015/11/13/osgi-jigsaw.html&quot;&gt;last blog post&lt;/a&gt;, it works on Java 9 and can take advantage of the modular JDK. And of course, it has been maturing and solving real world problems for over 15 years. However I have long acknowledged that the JDK itself has some unique problems that were difficult to solve with OSGi, which is why Jigsaw was needed. Back when Jigsaw slipped from Java 8, even Oracle’s Senior VP of Development &lt;a href=&quot;http://www.infoq.com/news/2014/07/Project-Jigsaw-On-Track-Java-9#anch112436&quot;&gt;agreed&lt;/a&gt; that this combination was a good solution.&lt;/p&gt;

&lt;p&gt;I think that the Java community would be better served by releasing Java 9 on time, including the modularised JDK provided by Jigsaw. Java today competes against many languages and platforms that are easier to use (or at least easier to &lt;em&gt;start&lt;/em&gt; using), cooler, smaller, and fast enough. It can stay relevant by slimming down, speeding up and implementing more useful features – not reimplementing poor replicas of features already developed years ago by the community.&lt;/p&gt;

&lt;p&gt;Jigsaw is great. It’s time to declare victory, release it, and move on.&lt;/p&gt;

</content>
   </entry>
 
   <entry>
     <title>OSGi and Java 9 Modules Working Together</title>
     <link href="http://njbartlett.name/2015/11/13/osgi-jigsaw.html"/>
     <updated>2015-11-13T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2015/11/13/osgi-jigsaw</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;The best thing about the &lt;a href=&quot;http://openjdk.java.net/projects/jigsaw/spec/sotms/&quot;&gt;Java Platform Module System&lt;/a&gt; – commonly known as Project Jigsaw, or &lt;a href=&quot;https://www.jcp.org/en/jsr/detail?id=376&quot;&gt;JSR 376&lt;/a&gt; – is that it has been used to break apart the monolithic Java runtime into smaller modules. This makes Java a more attractive implementation technology in many scenarios where it has historically been weak. For example, modern desktop or mobile applications can’t rely on having a pre-installed copy of Java on the user’s device, so you need to ship Java as part of your application. IoT is also driving developers to seek smaller installed size and memory footprint.&lt;/p&gt;

&lt;p&gt;Unfortunately, Jigsaw has some shortcomings as a module system for applications. I don’t want this blog post to be a critique of Jigsaw, but suffice to say there are many developers who will prefer to use OSGi for application modularity.&lt;/p&gt;

&lt;p&gt;Still, it would be very useful if we could run a modular OSGi application on a modular Java runtime. This would allow us to benefit from a minimal Java install, and at the same time use the full power of OSGi. Also it would help to hide much of Jigsaw’s complexity from application developers.&lt;/p&gt;

&lt;p&gt;I have just spent a day hacking together a &lt;a href=&quot;https://github.com/njbartlett/osgi_jigsaw&quot;&gt;demo&lt;/a&gt; that proves you can do this.&lt;/p&gt;

&lt;p&gt;I must emphasise that this is a throw-away prototype. You should &lt;strong&gt;absolutely not&lt;/strong&gt; start building on it. The OSGi Core Platform Expert Group (CPEG) will be working to specify official support for Java 9 features… I just wanted to show that a solution can exist, and perhaps feed into their discussions.&lt;/p&gt;

&lt;p&gt;NB: The following description may get confusing because of the overlapping concepts used by Jigsaw and OSGi, so I have to be very careful with terms. Whenever I say “module” I always mean a Jigsaw/Java 9 module, and when I say “bundle” I’m always talking about OSGi.&lt;/p&gt;

&lt;h2 id=&quot;use-case-osgi-bundles-in-a-known-platform-configuration&quot;&gt;Use Case: OSGi Bundles in a Known Platform Configuration&lt;/h2&gt;

&lt;p&gt;Suppose we have a Java runtime containing a known set of modules. We would like to start an OSGi Framework within the context of a module, such that the bundles in that framework can import packages from the platform modules.&lt;/p&gt;

&lt;p&gt;As background, OSGi has long used the concept of an Execution Environment (EE), which models the Java platform on which the framework is running. These have names such as &lt;code class=&quot;highlighter-rouge&quot;&gt;JavaSE-1.7&lt;/code&gt;. When an OSGi framework starts up, it detects what kind of platform it is running on and declares the EE as a capability that bundles can depend on.&lt;/p&gt;

&lt;p&gt;If you are unfamiliar with the term “capability” in this context, it is basically how all dependencies work in OSGi. Any bundle can declare a capability, which has a namespace and a set of attributes. Then any other bundle can require a capability, optionally with a filter expression. The OSGi Framework ensures that for every requirement, there exists a bundle providing a matching capability, otherwise the requirement will not resolve. OSGi additionally defines the meaning of some special capability namespaces. One of these is &lt;code class=&quot;highlighter-rouge&quot;&gt;osgi.ee&lt;/code&gt;, which is declared by the OSGi system bundle to indicate the Java platform version.&lt;/p&gt;

&lt;p&gt;Why can’t we work out a bundle’s platform dependency based on its imported packages? That’s not possible for two reasons. First, the packages from the Java platform are not versioned. Second, a large subset of packages – namely those starting with &lt;code class=&quot;highlighter-rouge&quot;&gt;java.&lt;/code&gt; (e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;java.net&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;java.lang&lt;/code&gt; etc) cannot be imported; they have to be loaded from the boot class loader. So bundles have to declare a requirement on the EE in order to ensure they can safely call methods like &lt;code class=&quot;highlighter-rouge&quot;&gt;Files.readAllBytes&lt;/code&gt; (added in Java 7) or &lt;code class=&quot;highlighter-rouge&quot;&gt;String.isEmpty&lt;/code&gt; (added in Java 6).&lt;/p&gt;

&lt;p&gt;An EE is basically a monolith: Java 7 is Java 7 and there are no other flavours. Things got a bit more complicated in Java 8 with the introduction of Compact Profiles… but these are basically still monolithic platforms. With just three profiles defined in the Java 8 specification, it was no problem for OSGi to define an EE for each profile. However in Java 9 there is a very large set of potential module combinations – too many to model with EEs.&lt;/p&gt;

&lt;p&gt;In my prototype I posit a capability namespace of &lt;code class=&quot;highlighter-rouge&quot;&gt;jmodule&lt;/code&gt; to describe the Java modules available in the platform. At runtime, the launcher inspects the set of available modules and uses them to declare the &lt;code class=&quot;highlighter-rouge&quot;&gt;jmodule&lt;/code&gt; capability. The relevant code looks like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Calculate the system capabilities&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;systemCapabilites&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getModule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getLayer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;modules&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;jmodule;jmodule=%s;version:Version=1.9&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;systemCapabilites&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Configure the framework&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configMap&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;configMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FRAMEWORK_SYSTEMCAPABILITIES_EXTRA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;formatAsList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;systemCapabilites&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Framework&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;framework&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frameworkFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;newFramework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;An OSGi bundle can now declare a requirement for a Jigsaw module as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;Require-Capability: jmodule; filter:=&quot;(jmodule=java.xml)&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;… and the OSGi Framework will refuse to resolve the above module if the required module (in this case, &lt;code class=&quot;highlighter-rouge&quot;&gt;java.xml&lt;/code&gt;) is not present in the platform. This is valuable because it protects against NoClassDefFoundErrors and ClassNotFoundExceptions from occurring at some unknown time during the life of the bundle. OSGi provides the assurance that the bundle will actually work on the platform that it finds itself on.&lt;/p&gt;

&lt;p&gt;But how do we know that our bundle depends on the &lt;code class=&quot;highlighter-rouge&quot;&gt;java.xml&lt;/code&gt; module? At the moment we have to use the &lt;code class=&quot;highlighter-rouge&quot;&gt;jdeps&lt;/code&gt; tool from the JDK:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;$ jdeps -module org.example.xml.jar
org.example.xml.jar -&amp;gt; java.base
org.example.xml.jar -&amp;gt; java.xml
org.example.xml.jar -&amp;gt; not found
   org.example.xml (org.example.xml.jar)
      -&amp;gt; java.io                                            java.base
      -&amp;gt; java.lang                                          java.base
      -&amp;gt; javax.xml.parsers                                  java.xml
      ...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;… which tells us that our bundle depends on &lt;code class=&quot;highlighter-rouge&quot;&gt;java.base&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;java.xml&lt;/code&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;java.base&lt;/code&gt; module is implicit so we can ignore it, but we do need to add &lt;code class=&quot;highlighter-rouge&quot;&gt;java.xml&lt;/code&gt; to the requirements.&lt;/p&gt;

&lt;p&gt;This process is manual and cumbersome right now, but in the future bnd should be able to generate the requirement automatically.&lt;/p&gt;

&lt;p&gt;We’re not done yet though, because the Java platform provides a whole bunch of packages that are not in the &lt;code class=&quot;highlighter-rouge&quot;&gt;java.*&lt;/code&gt; namespace. For example: &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.xml&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.sql.rowset&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;org.w3c.dom&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;org.omg.CORBA&lt;/code&gt; etc. We don’t need to do anything different in our OSGi bundles for these, because bnd will generate imports as normal. However we need the OSGi launcher to work out which packages are available from the platform modules. It can do this again by iterating over the modules using reflection:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// NB this sample ignores package versions for now&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;calculateExports&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packageNames&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getPackages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packageNames&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packageName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packageNames&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// ignore java.* packages&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packageName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;java.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isExported&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packageName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;packageName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is actually a massive boon to the OSGi Framework implementers. In previous Java releases, the Framework had to maintain a list of all the known packages provided by the platform; there was no standard API for enumerating classes or packages on the classpath (even if there were, it would reveal non-standard packages such as &lt;code class=&quot;highlighter-rouge&quot;&gt;sun.misc&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;com.sun.*&lt;/code&gt; and so on). Take a look at the &lt;a href=&quot;https://github.com/apache/felix/blob/trunk/framework/src/main/resources/default.properties&quot;&gt;properties file that Felix maintains&lt;/a&gt; for this purpose… it’s larger than you might expect.&lt;/p&gt;

&lt;h2 id=&quot;implementation-issues&quot;&gt;Implementation Issues&lt;/h2&gt;

&lt;p&gt;In the demo I have copied the source code for Apache Felix into my module. I did this to give myself freedom to hack the implementation, but so far have hardly needed to — more on that shortly.&lt;/p&gt;

&lt;p&gt;Most of the code is in &lt;a href=&quot;https://github.com/njbartlett/osgi_jigsaw/blob/master/nbartlett-jigsaw-osgi/src/nbartlett.jigsaw_osgi/nbartlett/osgi_jigsaw/Main.java&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;nbartlett.osgi_jigsaw.Main&lt;/code&gt;&lt;/a&gt;, and it’s mostly just a vanilla OSGi launcher. The main differences are the &lt;code class=&quot;highlighter-rouge&quot;&gt;jmodule&lt;/code&gt; capabilities and system bundle exports as already described.  The &lt;code class=&quot;highlighter-rouge&quot;&gt;module-info.java&lt;/code&gt; looks like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbartlett&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;jigsaw_osgi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;	
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;hooks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;weaving&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;launch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;startlevel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;startlevel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;wiring&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;wiring&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;packageadmin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;startlevel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;resolver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;tracker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;osgi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All of the packages of the OSGi Framework have to be exported by the module wrapping it. This is necessary because the bundles actually load into a different module – the “unnamed” module – and so we need Jigsaw to permit access to the OSGi API packages. If we fail to do this, the following error occurs:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;java.lang.IllegalAccessError: superinterface check failed: class org.example.Activator
(in module: Unnamed Module) cannot access class org.osgi.framework.BundleActivator (in
module: nbartlett.jigsaw_osgi), org.osgi.framework is not exported to Unnamed Module&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After fixing this, I encountered the following error when the OSGi Framework tried to instantiate the &lt;code class=&quot;highlighter-rouge&quot;&gt;BundleActivator&lt;/code&gt; from any bundle:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;java.lang.IllegalAccessException: class org.apache.felix.framework.Felix (in module
nbartlett.jigsaw_osgi) cannot access class org.example.Activator because module
nbartlett.jigsaw_osgi does not read &amp;lt;unnamed module @5cee5251&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This one was quite a puzzle! It turns out that if you create an instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt; and use it to load classes dynamically, those classes will always belong to the unnamed module. In order to load classes into a real module you have to use &lt;code class=&quot;highlighter-rouge&quot;&gt;ModuleClassLoader&lt;/code&gt;. However this class is final, so OSGI cannot override &lt;code class=&quot;highlighter-rouge&quot;&gt;loadClass&lt;/code&gt; to implement OSGi loading rules.&lt;/p&gt;

&lt;p&gt;Incidentally, the upshot is that &lt;strong&gt;any&lt;/strong&gt; code that looks like the following – and this is a very common code pattern – will fail from inside a module other than the unnamed module:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;URLClassLoader&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;URLClassLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urls&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClassLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clazz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;loadClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;blah.Blah&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;clazz&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;newInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &amp;lt;-- this line fails from within a named module&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It fails because &lt;code class=&quot;highlighter-rouge&quot;&gt;blah.Blah&lt;/code&gt; belongs to the unnamed module, and our module doesn’t require unnamed. You can’t write &lt;code class=&quot;highlighter-rouge&quot;&gt;requires unnamed&lt;/code&gt; in the &lt;code class=&quot;highlighter-rouge&quot;&gt;module-info.java&lt;/code&gt;, but you can dynamically add the requirement as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getModule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addReads&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getUnnamedModule&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For now, we have to accept that OSGi bundles will load into the unnamed module. It’s an open question whether we can map them into the OSGi module, or even a module for each bundle. By adding the above line to Felix (&lt;code class=&quot;highlighter-rouge&quot;&gt;BundleWiringImpl&lt;/code&gt; line 731), the Framework is able to load the bundle activator, and OSGi starts up:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;g! lb
START LEVEL 1
   ID|State      |Level|Name
    0|Active     |    0|System Bundle (0.0.0)
    1|Active     |    1|Apache Felix Gogo Command (0.14.0)
    2|Active     |    1|Apache Felix Gogo Runtime (0.12.1)
    3|Active     |    1|Apache Felix Gogo Shell (0.10.0)
    4|Active     |    1|org.example.xml (0.0.0.201511120014)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In my demo I installed and started the three bundles of Felix Gogo, which gives me an interactive shell, and a fourth bundle that contains some XML parsing code. This code forces a dependency on the &lt;code class=&quot;highlighter-rouge&quot;&gt;java.xml&lt;/code&gt; module and the &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.xml.parsers&lt;/code&gt; package from the platform, both of which are satisfied by the system bundle.&lt;/p&gt;

&lt;h2 id=&quot;use-case-configuring-the-platform-for-a-set-of-bundles&quot;&gt;Use Case: Configuring the Platform for a Set of Bundles&lt;/h2&gt;

&lt;p&gt;Above we had a known platform and wanted OSGi to validate the bundles we wanted to run on it. Flipping this around, what if we have a set of bundle – our application – and want to work out the minimal platform that will run it?&lt;/p&gt;

&lt;p&gt;You can already do this – kind of – with existing tools. The jdeps tool can print the module dependencies of each of your OSGi bundles, so the modules you need in your platform are just the aggregate of those jdeps outputs. The OSGi framework module I defined above doesn’t have any dependencies aside from &lt;code class=&quot;highlighter-rouge&quot;&gt;java.base&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you build your bundles using the future version of bnd that generates &lt;code class=&quot;highlighter-rouge&quot;&gt;jmodule&lt;/code&gt; requirements for you, then you don’t need to run jdeps. It will be very simple to generate the aggregate dependencies just by looking at the bundle manifests. We can create a tool that builds an application artifact, including the minimal Java runtime modules plus OSGi bundles, as part of bnd/Bndtools. We already have an exporter for “standalone” JAR files, this would just be an extension of the same principle. But that’s for the future.&lt;/p&gt;

&lt;h2 id=&quot;open-questions&quot;&gt;Open Questions&lt;/h2&gt;

&lt;p&gt;Here are some of the issues I haven’t even touched on, that will need a good answer before OSGi and Java 9 Module interop is a reality:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Versions!&lt;/strong&gt; Jigsaw chose to ignore versions, so they will have to be layered on top somehow. This sounds like a recipe for lots of competing and incompatible schemes… the Maven way, the Gradle way, the OSGi way, etc. Should OSGi infer versions for the exports from the platform? If so, where should those come from?&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Bundle-Module Mapping&lt;/strong&gt;. The bundle classes load into the unnamed module, meaning that we have exactly as much protection and access control between bundles as OSGi has always had – no more, no less – and that’s fine. However, by using &lt;code class=&quot;highlighter-rouge&quot;&gt;ModuleClassLoader&lt;/code&gt; we may be able to map each bundle to a Jigsaw module and benefit from increased isolation. I didn’t have time to figure out whether this would be possible.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Dynamics&lt;/strong&gt;. With this prototype we can install, update and uninstall OSGi bundles dynamically. But if a newly installed bundle has requirements that are not satisfied by the current set of platform modules, can we install the required module into the platform dynamically? It looks like probably not, that’s just not within the scope of Jigsaw.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Uses Constraints&lt;/strong&gt;. This is a tricky problem to describe and solve… see my &lt;a href=&quot;http://njbartlett.name/2011/09/02/uses-constraints.html&quot;&gt;post&lt;/a&gt; on the subject of uses constraints. Jigsaw module descriptors do not provide any information on the interdependencies between packages (e.g. the fact that &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.sql&lt;/code&gt; uses &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.transaction.xa&lt;/code&gt;, so if you import both of these packages then you really have to import them from the same source). Without this info, it will not be safe for OSGi bundles to offer exports that subtitute for exports from the platform.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Services&lt;/strong&gt;. Jigsaw has a service model, though quite different from OSGi services. It would probably be useful for services from the platform to be bridged into the OSGi service registry.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Bidirectional Dependencies&lt;/strong&gt;. Can we ever build a bidirectional link between OSGi and Jigsaw, so that bundles and modules can sit side-by-side in cooperative harmony? I don’t particularly care about this use case – I believe OSGi is the better application module system so it makes sense for the dependencies to flow downwards but not upwards. However, somebody might want to do this I suppose. It will be tricky though because of the dynamics in OSGi and lack of versions in Jigsaw.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Evolving EEs&lt;/strong&gt;. The CPEG will need to decide what to do with EEs. Maybe they will be supplemented with something like the&lt;code class=&quot;highlighter-rouge&quot;&gt;jmodule&lt;/code&gt; capability, or perhaps something completely different. We probably still need an EE to define the version and content of &lt;code class=&quot;highlighter-rouge&quot;&gt;java.base&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;getting-it&quot;&gt;Getting It&lt;/h2&gt;

&lt;p&gt;The prototype code is on GitHub at &lt;a href=&quot;https://github.com/njbartlett/osgi_jigsaw&quot;&gt;njbartlett/osgi_jigsaw&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To build the code, execute &lt;code class=&quot;highlighter-rouge&quot;&gt;./build.sh&lt;/code&gt; from the &lt;code class=&quot;highlighter-rouge&quot;&gt;nbartlett-jigsaw-osgi&lt;/code&gt; directory. To run, execute &lt;code class=&quot;highlighter-rouge&quot;&gt;./run.sh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to my employer &lt;a href=&quot;https://paremus.com/&quot;&gt;Paremus&lt;/a&gt; for funding this research. We want to help our customers to build and deploy manageable, modular software, whatever the implementation technology.&lt;/p&gt;

&lt;p&gt;Thanks to Sander Mak’s &lt;a href=&quot;http://branchandbound.net/blog/java/2015/10/osgi-to-jigsaw/&quot;&gt;blog post&lt;/a&gt; for helping me to setup a Jigsaw workspace (though I can’t let this pass with commenting on his last paragraph… “vastly less complex”? Seriously dude are you feeling okay?)&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>What's New in Declarative Services 1.3?</title>
     <link href="http://njbartlett.name/2015/08/17/osgir6-declarative-services.html"/>
     <updated>2015-08-17T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2015/08/17/osgir6-declarative-services</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;&lt;strong&gt;I’d like to tell you about two really cool new features in OSGi Declarative
Services&lt;/strong&gt;. They’re so cool that I feel kind of guilty for blogging about them,
because some of the kudos may accrue to me even though I have done absolutely
none of the work to either specify or implement them. So bear in mind that I’m
only your humble messenger.&lt;/p&gt;

&lt;h3 id=&quot;configuration-property-types&quot;&gt;Configuration Property Types&lt;/h3&gt;

&lt;p&gt;As a bit of background, in Declarative Services (DS) it has always been possible to write configurable
components by passing a Map into the activate method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ServerComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@Activate&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configProps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindHost&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configProps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;host&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Integer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configProps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;port&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;ServerSocket&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServerSocket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InetSocketAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bindHost&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There are some great things about the way DS handles configuration. First, the
component itself has no idea about the origin of the config data… it could
come from a properties file, or an XML file, or a database record, or
transmitted over the air from a cellular provider, etc. Because the component
is not coupled to the physical mechanism, we can change that mechanism easily
without updating the code of all our components.&lt;/p&gt;

&lt;p&gt;Second, the configuration is passed all-at-once and can be dynamically changed.
Some other DI frameworks inject configuration data one field at a time
(&lt;code class=&quot;highlighter-rouge&quot;&gt;setHost&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;setPort&lt;/code&gt;…). Where they support dynamic reconfiguration at all, they
tend to need methods to let the component know that a series of config changes
is starting and ending, so that it knows when it’s safe to reconfigure. Otherwise
the component could end up using a mixture of old and new config.&lt;/p&gt;

&lt;p&gt;There is a problem, however. Did you notice that my code sample above had no
error handling at all? What if the &lt;code class=&quot;highlighter-rouge&quot;&gt;host&lt;/code&gt; property was missing from the map?
What if the port was given as a String rather than an integer?  What if it
contained invalid numeric characters? Some fields may be optional, where do we
specify the defaults? It turns out that most components have to do quite a bit
of work to convert, parse and validate their configuration. There are libraries
that encapsulate this – such as the Configurable API from bnd – but
they add a runtime dependency, which is inconvenient (though manageable in OSGi
with &lt;a href=&quot;/2014/05/26/static-linking.html&quot;&gt;static linking&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Declarative Services 1.3 – part of the OSGi Release 6 compendium spec, which
was released to the public last week – improves this enormously. It’s now
possible to define a custom type for the configuration, rather than a generic
Map. For example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServerConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.0.0.0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;enableSSL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ServerComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@Activate&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServerConfig&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cfg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ServerSocket&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServerSocket&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InetSocketAddress&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cfg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cfg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()));&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now the DS runtime is doing all the work of pulling out fields, converting them
to the correct type and so on. If there are any conversion errors, or missing
fields that don’t have defaults, then DS will refuse to load our component and
will write an appropriate message into the OSGi Log.&lt;/p&gt;

&lt;p&gt;This feature is known as “Configuration Property Types”. You may wonder why
an annotation is used rather than an interface, given that we don’t actually
use it like an annotation. There are a few reasons: in
annotations it’s trivial to provide defaults; the methods cannot have
parameters; and the return types allowed in an annotation are restricted to
types that mesh well with configuration data.&lt;/p&gt;

&lt;p&gt;Of course this version of DS interoperates with the OSGi Metatype specifcation,
so that the administrators of our application can know what fields and types are
actually expected. The metadata is generated at build time if we just add a couple
more annotations:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@ObjectClassDefinition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Server Configuration&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServerConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.0.0.0&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;enableSSL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Designate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ocd&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServerConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ServerComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;… and, from this definition, tools like the Apache Felix Web Console can automatically
generate an admin GUI for our component:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/ds1.3/webconsole.png&quot; width=&quot;499&quot; height=&quot;185&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;prototype-scope-services&quot;&gt;Prototype Scope Services&lt;/h3&gt;

&lt;p&gt;The second really cool feature is support for &lt;em&gt;prototype scope&lt;/em&gt; in services.
The prototype scope has been available in the OSGi Core R6 specification for
about a year now, but there was a significant gap between the release of the
Core and Compendium documents. So until now we had to drop down to the
low-level OSGi API in order to use prototype scope. In DS 1.3 we can use
annotations and a more convenient runtime API instead.&lt;/p&gt;

&lt;p&gt;Prototype scope is where a service has the ability to create multiple instances
on demand. Traditionally, most OSGi services were conceptually singletons: each
registry entry corresponded to a single back-end service instance that was
shared by all consumers. (Aside: there were additionally bundle-scoped
services, where each consumer bundle got its own instance of the service
object, but if you used a service multiple times from within the same bundle
you would still share the same instance).&lt;/p&gt;

&lt;p&gt;This model had to be enhanced, since sometimes each consumer really needs to
have its own instance of the service. Also some consumers need to have
programmatic control over the creation and destruction of instances, in order
to fit in with an external lifecycle. An example of this would be in web
requests – some web standards (for example JAX-RS) require services to be
instantiated and then destroyed in every request. Hence the prototype scope was
added. This is an opt-in feature: both the provider and the consumer of the
service need to be aware that it is being used.&lt;/p&gt;

&lt;p&gt;In DS 1.3, a provider can opt in to the prototype scope very easily with an
attribute on the @Component annotation:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServiceScope&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PROTOTYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As a consumer there are a few more choices. When we consume a service with the
@Reference annotation, we can use an attribute to request a new instance per
component:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Reference&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ReferenceScope&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PROTOTYPE_REQUIRED&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Using this annotation, each component that uses the Foo service will get its
own instance. However within each component, the same Foo instance will be used
repeatedly. Alternatively, the consumer can create and destroy instances
programmatically whenever it wants – this requires the consumer to use a bit
of API from DS as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComponentServiceObjects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fooFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@Reference&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ReferenceScope&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;PROTOTYPE_REQUIRED&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setFooFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ComponentServiceObjects&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fooFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;fooFactory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fooFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myFoo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fooFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// do something interesting with myFoo ...&lt;/span&gt;

  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fooFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ungetService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The use of the ComponentServiceObjects interface means we are no longer
building strict POJOs, but still this interface is easily mockable for testing
purposes.&lt;/p&gt;

&lt;h3 id=&quot;getting-it&quot;&gt;Getting It&lt;/h3&gt;

&lt;p&gt;The specification for DS 1.3 is available now from &lt;a href=&quot;http://www.osgi.org/Download/Release6&quot;&gt;http://www.osgi.org/Download/Release6&lt;/a&gt;. Felix SCR 2.0 implements the specification and can be downloaded from &lt;a href=&quot;http://felix.apache.org/downloads.cgi&quot;&gt;http://felix.apache.org/downloads.cgi&lt;/a&gt;. For full metatype support you will need Felix Metatype 1.1 from the same page.&lt;/p&gt;

&lt;p&gt;To build components using the annotations you will need a development build of bnd/Bndtools 3.0. To install this, go to &lt;a href=&quot;http://bndtools.org/installation.html&quot;&gt;http://bndtools.org/installation.html&lt;/a&gt; and follow the instructions for installing a developer snapshot build.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Announcing the bnd Maven Plugin</title>
     <link href="http://njbartlett.name/2015/03/27/announcing-bnd-maven-plugin.html"/>
     <updated>2015-03-27T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2015/03/27/announcing-bnd-maven-plugin</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;I am pleased to announce the availability of a new Maven plugin for building
OSGi bundles, based on bnd. The plugin is called &lt;code class=&quot;highlighter-rouge&quot;&gt;bnd-maven-plugin&lt;/code&gt; and it will
be developed as part of the wider bnd and Bndtools projects.&lt;/p&gt;

&lt;p&gt;The plugin has been kindly donated by one of Paremus’ customers – a very well
known company whose identity we expect to be able to confirm in due course –
under the terms of the Apache License version 2.&lt;/p&gt;

&lt;p&gt;You might very well wonder: why did we build a new Maven plugin for OSGi
development? Most OSGi developers who use Maven today are using the
&lt;code class=&quot;highlighter-rouge&quot;&gt;maven-bundle-plugin&lt;/code&gt; from Apache Felix. That plugin is mature and stable but
it does have a number of issues that our customer wanted resolved.&lt;/p&gt;

&lt;p&gt;The first major issue with maven-bundle-plugin is that it replaces Maven’s
default plugin for JAR generation (the &lt;code class=&quot;highlighter-rouge&quot;&gt;maven-jar-plugin&lt;/code&gt;). This means that it
must use a different packaging type – “bundle” instead of “jar” – and must
use the &lt;code class=&quot;highlighter-rouge&quot;&gt;extensions=true&lt;/code&gt; setting to override Maven’s default lifecycle.  As a
result, the output artifacts are harder to consume in ordinary non-OSGi
projects. Therefore, many Maven developers either don’t bother to release OSGi
bundles at all because of the hassle, or they release both a “plain JAR” &lt;em&gt;and&lt;/em&gt;
a separate OSGi bundle. This is deeply frustrating because OSGi bundles already
are plain JARs!… they can be used unalterered in non-OSGi applications.&lt;/p&gt;

&lt;p&gt;The new bnd-maven-plugin instead hooks into Maven’s &lt;code class=&quot;highlighter-rouge&quot;&gt;process-classes&lt;/code&gt; phase. It
prepares all of the generated resources, such as MANIFEST.MF, Declarative
Services descriptors, Metatype XML files and so on, under the &lt;code class=&quot;highlighter-rouge&quot;&gt;target/classes&lt;/code&gt;
directory, where they will be automatically included by the standard
maven-jar-plugin (with one caveat discussed below).&lt;/p&gt;

&lt;p&gt;The second issue is that maven-bundle-plugin has some questionable features and
design choices. For example it automatically exports &lt;strong&gt;all&lt;/strong&gt; packages that do not
contain the substrings “impl” or “internal”. The motivation was
understandable at the time – it is closer to normal Java with all packages
being implicitly exported – but this is really just wrong from a modularity point
of view, and goes against OSGi best practices. The bnd-maven-plugin instead
includes all packages from the project in the bundle but exports nothing by
default. The developer must choose explicitly which packages are exported.&lt;/p&gt;

&lt;p&gt;The third issue with maven-bundle-plugin is that it is difficult to use in an
incremental build environment. In Bndtools we have had literally years of
discussions about how to best accommodate Maven users while still supporting
the rapid development cycle that Bndtools users love. The new plugin will make
this easier: for example after the &lt;code class=&quot;highlighter-rouge&quot;&gt;process-classes&lt;/code&gt; phase has completed, the
content of the &lt;code class=&quot;highlighter-rouge&quot;&gt;target/classes&lt;/code&gt; directory is already a valid OSGi bundle,
albeit in folder form rather than a JAR file. Also the new plugin takes its bnd
instructions from the bnd.bnd file in each project, rather than from a funky
XML encoding of those instructions deep inside the POM.&lt;/p&gt;

&lt;p&gt;Finally, we believe that by delivering a Maven plugin directly from the bnd
project, we can more quickly take advantage of new features in bnd, and develop
features in bnd that directly benefit Maven users. Note however that the Gradle
and Ant integrations of bnd will still be supported: we want everybody to use
bnd to build their OSGi bundles, irrespective of IDE and build system.&lt;/p&gt;

&lt;p&gt;So much for motivation, let’s look at some of the technical details.&lt;/p&gt;

&lt;p&gt;The plugin has been released as version 2.4.1 because there was a previous
experimental plugin with the same name. That experiment was not a success, and
we abandoned it some time ago – the new plugin is a complete rewrite. The
version of the plugin will track the version of bnd itself, so 2.4.1 of the
plugin builds against 2.4.1 bnd, which is released and available from Maven
Central.  From now on we will work on version 3.0, which will track version 3.0
of bnd.&lt;/p&gt;

&lt;p&gt;The plugin generates the JAR manifest into
&lt;code class=&quot;highlighter-rouge&quot;&gt;target/classes/META-INF/MANIFEST.MF&lt;/code&gt;, but by default the maven-jar-plugin
ignores this file and replaces it with an empty, non-OSGi manifest. In order
to pick up the generated manifest it is necessary to set the following
configuration, which can be done just once in your parent POM:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-jar-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;useDefaultManifestFile&amp;gt;true&amp;lt;/useDefaultManifestFile&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The plugin is available now &lt;a href=&quot;https://oss.sonatype.org/#nexus-search;quick~bnd-maven-plugin&quot;&gt;from Maven
Central&lt;/a&gt; or &lt;a href=&quot;https://bintray.com/bnd/bnd/bnd-maven-plugin/view&quot;&gt;jCenter&lt;/a&gt;&lt;/strong&gt;.
It is not yet thoroughly documented, although bnd itself does have very good
&lt;a href=&quot;http://bnd.bndtools.org/&quot;&gt;documentation&lt;/a&gt;. All options from bnd automatically
work in bnd-maven-plugin, with the exception of “sub bundles” (&lt;code class=&quot;highlighter-rouge&quot;&gt;-sub&lt;/code&gt;) since
Maven projects are meant to produce exactly one output artifact per project.&lt;/p&gt;

&lt;p&gt;To add the plugin to your project, insert the following into your POM:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;biz.aQute.bnd&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;bnd-maven-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.4.1&amp;lt;/version&amp;gt;

    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;bnd-process&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We have &lt;a href=&quot;https://github.com/bndtools/bnd/tree/bnd-maven-plugin-2.4.1/bnd-maven-plugin-examples&quot;&gt;example projects&lt;/a&gt; to get started. Questions, problems or offers of help can be can be directed to the &lt;a href=&quot;https://groups.google.com/forum/#!forum/bndtools-users&quot;&gt;bnd/Bndtools mailing list&lt;/a&gt;.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Static Linking in OSGi</title>
     <link href="http://njbartlett.name/2014/05/26/static-linking.html"/>
     <updated>2014-05-26T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2014/05/26/static-linking</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;When building native executables in a language like C or C++, we have a choice about how to deal with the libraries our code depends on. We can choose to link them statically, meaning that the library contents are physically copied into the executable file at build time, or we can link dynamically which means the library contents must be found externally to the executable by a special runtime component called the linker.&lt;/p&gt;

&lt;p&gt;Static linking has the great advantage that the executable can rely on always having the library it needs, and it’s always the correct version. Installation is a breeze because there’s just a single file to copy. The clear downside of static linking is that commonly used libraries will be duplicated in lots of executables, and therefore take more disk space and perhaps memory.&lt;/p&gt;

&lt;p&gt;In standard Java, a JAR is a kind of executable that has dependencies on libraries. However static linking is unheard of in this world because it is terribly unsafe. All JARs sit together in a global classpath – if one JAR contains a copy of a library and another JAR contains a copy of the same library then the first one on the classpath will always “win”. If the two copies are of different versions then chaos ensues.&lt;/p&gt;

&lt;p&gt;Therefore the state of the art in standard Java is a kind of dynamic linking, except without any metadata in the JARs to declare exactly what we should be linked with… and no linker! Instead, developers often have find dependencies through a process of trial-and-error: keep adding JARs to the classpath until all the &lt;code class=&quot;highlighter-rouge&quot;&gt;NoClassDefFoundErrors&lt;/code&gt; go away.&lt;/p&gt;

&lt;p&gt;OSGi applications predominantly use dynamic linking as well. It’s a lot more manageable because we have precise metadata defining the dependencies, and the OSGi Framework itself can be seen as a kind of linker. However, static linking is also perfectly possible and safe because of the isolation provided by OSGi, and it has many of the same advantages as statically linked native executables. Bundles with fewer dependencies are simply easier to manage. To put it another way: OSGi is the best system I have ever seen for managing dependencies, but the easiest artefacts to manage are still those with no dependencies at all.&lt;/p&gt;

&lt;p&gt;Static linking in OSGi is sometimes done by means of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Bundle-ClassPath&lt;/code&gt;, which allows us to embed an entire library JAR inside a bundle. This works, but it can inflate the size of our bundle quickly because we pull in the entire JAR rather than just the parts we need. An alternative solution is to use &lt;code class=&quot;highlighter-rouge&quot;&gt;Private-Package&lt;/code&gt; to include individual packages out of the dependency JARs. However once a package is added this way it becomes a permanent part of our bundle until we explicitly remove it from the &lt;code class=&quot;highlighter-rouge&quot;&gt;Private-Package&lt;/code&gt; list. In the future our core code might change such that some or all of these packages will not be needed. Will we remember to review &lt;code class=&quot;highlighter-rouge&quot;&gt;Private-Package&lt;/code&gt; regularly to ensure everything there is actually still used? Not likely.&lt;/p&gt;

&lt;h3 id=&quot;a-better-way&quot;&gt;A Better Way&lt;/h3&gt;

&lt;p&gt;And so we come to a little-known bnd instruction called &lt;code class=&quot;highlighter-rouge&quot;&gt;Conditional-Package&lt;/code&gt;. This instruction is used to include a package or set of packages if (and &lt;em&gt;only&lt;/em&gt; if) they are used from the core packages of our bundle -– where core packages are defined as those that are listed in &lt;code class=&quot;highlighter-rouge&quot;&gt;Private-Package&lt;/code&gt; and/or &lt;code class=&quot;highlighter-rouge&quot;&gt;Export-Package&lt;/code&gt;. We can even use wildcards, and bnd will calculate the minimum set of packages that need to be included. For example, many of my bnd files include a line like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;Conditional-Package: org.example.util.*&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;where the &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.util&lt;/code&gt; prefix is for a whole set of packages designed as generic utilities.&lt;/p&gt;

&lt;h3 id=&quot;service-vs-library&quot;&gt;Service vs Library&lt;/h3&gt;

&lt;p&gt;Static linking with &lt;code class=&quot;highlighter-rouge&quot;&gt;Conditional-Package&lt;/code&gt; can help to resolve a common head-scratcher when designing OSGi bundles.&lt;/p&gt;

&lt;p&gt;Sometimes we want to write a piece of utility code that will be used across a number of other bundles, but that doesn’t seem to warrant a service interface. Services are great for application components that can be implemented in more than one way, but sometimes there is only one conceivable implementation. A classic example is encoding, e.g. Base64. When a client wants to convert to/from Base64 representation, it doesn’t want to have an alternative encoding swapped in at runtime! In this case the client is quite happy to be tightly coupled to a specific implementation of the function it is calling.&lt;/p&gt;

&lt;p&gt;It feels wrong to export a package that contains implementation code in OSGi. Ideally, exports are for service interfaces, i.e. &lt;em&gt;contracts&lt;/em&gt;. Implementation code is subject to rapid change and is hard to version correctly (tools like bnd’s baselining can’t detect semantic changes in executable code, only on method signatures). Nevertheless we still want to reuse the Base64 encoder across all the bundles that need it. So we use &lt;code class=&quot;highlighter-rouge&quot;&gt;Conditional-Package&lt;/code&gt; to &lt;em&gt;include&lt;/em&gt; that functionality directly. No versioning headaches because the bundle always gets the exact version was built with.&lt;/p&gt;

&lt;p&gt;Incidentally this practice doesn’t violate the DRY (Don’t Repeat Yourself) principle because the source code is still defined in just one place; it’s the compiled class files that are copied.&lt;/p&gt;

&lt;h3 id=&quot;contraindications&quot;&gt;Contraindications&lt;/h3&gt;

&lt;p&gt;A few words of warning. Like all power tools, &lt;code class=&quot;highlighter-rouge&quot;&gt;Conditional-Package&lt;/code&gt; is dangerous if misused. When we pull a package into our bundle we inherit all of its dependencies, so it is best to do this with small, coherent packages that do not have a large tree of transitive dependencies. Try to design your packages so that they do only one thing each… don’t make a big generic &lt;code class=&quot;highlighter-rouge&quot;&gt;util&lt;/code&gt; package, instead make subpackages such as &lt;code class=&quot;highlighter-rouge&quot;&gt;util.xml&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;util.io&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;util.encoding&lt;/code&gt; and so on. Note that &lt;code class=&quot;highlighter-rouge&quot;&gt;Conditional-Package&lt;/code&gt; will pull in any transitive package dependencies that match the pattern we have specified – all others are treated as external dependencies and end up in &lt;code class=&quot;highlighter-rouge&quot;&gt;Import-Package&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Using a qualified or prefixed wildcard such as &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.util.*&lt;/code&gt; is okay. Using a bare wildcard is &lt;strong&gt;not&lt;/strong&gt; okay. I have seen this done accidentally: as a result, the bundle contained large chunks of the JRE as well as OSGi core packages.&lt;/p&gt;

&lt;p&gt;Another danger is if we pull in packages that are used by an exported interface. Take the following example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kn&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;a.A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
	
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doSomeThing&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This should be familiar to OSGi developers as a &lt;em&gt;uses&lt;/em&gt; constraint, because &lt;code class=&quot;highlighter-rouge&quot;&gt;B&lt;/code&gt; communicates type &lt;code class=&quot;highlighter-rouge&quot;&gt;A&lt;/code&gt; from package &lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt;. It would be very bad to include a private copy of package &lt;code class=&quot;highlighter-rouge&quot;&gt;a&lt;/code&gt; in our bundle, because it would not be compatible with other bundles’ idea of what the package looks like. Actually bnd will report a build warning when it sees an exported package having a &lt;em&gt;uses&lt;/em&gt; constraint on a private package, so you easily can avoid this situation.&lt;/p&gt;

&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;Static linking in OSGi can improve your bundles, making them safer and easier to deploy. As always there is a trade-off and the technique can lead to larger bundles overall, but this can be mitigated by keeping packages small and coherent.&lt;/p&gt;

</content>
   </entry>
 
   <entry>
     <title>Maven Support in Bndtools — Future Directions</title>
     <link href="http://njbartlett.name/2013/06/13/bndtools-2.2-maven.html"/>
     <updated>2013-06-13T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2013/06/13/bndtools-2.2-maven</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Enhancing support for Maven is a perennial topic amongst Bndtools developers and users, and during the Bndtools Hackathon last week we discussed the topic in-depth.
As a result, we have determined that there will be two broad approaches towards Maven support in Bndtools. The choice between these approaches will be largely a matter of taste, and the user’s attitude and motivation towards the tools.&lt;/p&gt;

&lt;h2 id=&quot;maven-first&quot;&gt;“Maven First”&lt;/h2&gt;

&lt;p&gt;One set of developers comes from the Maven world and is generally happy with the “Maven Way”; they do not want it to change significantly. We feel that these users are already well served by the &lt;a href=&quot;https://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html&quot;&gt;Felix Bundle Plugin&lt;/a&gt;, &lt;a href=&quot;http://eclipse.org/m2e/&quot;&gt;m2eclipse&lt;/a&gt; and even other IDEs such as NetBeans.&lt;/p&gt;

&lt;p&gt;Bndtools cannot and should not compete with those tools as a generic Maven-centric IDE; yet we can still add value. For example even when using m2eclipse, we can offer our wizards for creating Declarative Services or Blueprint components, and we can provide a great way to launch, test and debug OSGi applications from within the IDE.&lt;/p&gt;

&lt;p&gt;Also our support for the OSGi R5 Repositories and Resolver specifications means that you can work with bundles built by Maven and deployed to a repository – e.g. Nexus, Artifactory, or even just the bundles installed in your “local” repository – resolve your top-level bundles and generate an application descriptor. This descriptor can then be fed back into the Maven build chain to create a fully assembled and deployed application. We feel we can do a much better job of this than other tools because we take full advantage of OSGi’s rich Capabilities and Requirements dependency model.&lt;/p&gt;

&lt;p&gt;We call the above a “Maven first” approach. To make it work, certain parts of Bndtools will have to be decoupled from the internal build system so that, for example, we can resolve and run without having to be inside a bnd-style project. This decoupling is anyway good for Bndtools’ internal modularity, and we expect to complete it in time for the 2.2 release.&lt;/p&gt;

&lt;h2 id=&quot;bnd-first&quot;&gt;“Bnd First”&lt;/h2&gt;

&lt;p&gt;The second approach is for developers who prefer a more OSGi-centric development process, and who want to use the advanced build-time features of bnd/Bndtools while still using a fully Maven-based offline build.&lt;/p&gt;

&lt;p&gt;For example one of the most exciting features we are working on in 2.2 is &lt;em&gt;baselining&lt;/em&gt;, which (briefly) means the tool helps to ensure your packages and bundles are correctly versioned according to the OSGi Semantic Versioning guidelines, by breaking the build when versions are incorrect, and offering quick-fixes to get it back into shape. Ferry Huberts has written an overview on &lt;a href=&quot;https://plus.google.com/u/0/115799306929323170405/posts/fQ6mcdz1DeU&quot;&gt;his blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another feature that Bndtools has always offered is very fast incremental builds, which are integrated with the launching subsystem so that your code is compiled, built and already running in your application as soon as you save it. Incremental building is always a problem with Maven, and even m2eclipse doesn’t do it very well (though it seems to be improving gradually).&lt;/p&gt;

&lt;p&gt;These features are hard-to-impossible to implement given the control (or rather, &lt;em&gt;lack&lt;/em&gt; of control) afforded to us by the existing Felix Bundle Plugin. That plugin basically only creates the JAR file during the packaging phase, whereas in Bndtools bnd maintains the build model so that it can be used in Eclipse, Ant, Maven, Gradle and others.&lt;/p&gt;

&lt;p&gt;Therefore we are working on a new plugin for Maven that allows bnd to take more control. We call this the “bnd first” approach. Actually the plugin was started by Toni Menzel, and Peter Kriens has begun enhancing it. So far it looks extremely promising, but unfortunately it is still quite experimental and will probably not be release-quality in time for 2.2. If you are interested in trying it before then, please engage on the &lt;a href=&quot;https://groups.google.com/forum/?fromgroups#!forum/bndtools-users&quot;&gt;Bndtools mailing list&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;other-tools&quot;&gt;Other Tools&lt;/h2&gt;

&lt;p&gt;As ever, enhancing Maven support does not mean that we are reducing our support for existing Ant builds. We will continue to offer a modular Ant-based build system with our project templates, and in fact some of the work done at the hackathon by PK Søreide helped to improve the performance of our Ant tasks by a factor of three to four.&lt;/p&gt;

&lt;p&gt;Also, Paul Bakker worked on a new Gradle build template, which turned out up to &lt;em&gt;ten&lt;/em&gt; times faster than the old Ant build! We hope to have this ready in 2.2.&lt;/p&gt;

&lt;p&gt;So our focus continues to be this: enabling you to be as productive as possible as an OSGi developer, irrespective of your choice of build tool.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Bndtools 2.1 Released</title>
     <link href="http://njbartlett.name/2013/02/11/bndtools2.1-released.html"/>
     <updated>2013-02-11T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2013/02/11/bndtools2.1-released</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;&lt;em&gt;GUEST POST: This post was written by my friend and open-source-colleague Ferry Huberts. Read the original &lt;a href=&quot;https://plus.google.com/u/0/115799306929323170405/posts/ZoN23b3Hr6t&quot;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We just released Bndtools version 2.1. We’re very proud of it and are convinced that it will make your life as an OSGi developer much easier. Easier than any other tool around.&lt;/p&gt;

&lt;p&gt;All together we believe that Bndtools is now the foremost tool for developing OSGi applications, and continues our mission to make OSGi development easier and more productive than traditional Java development.&lt;/p&gt;

&lt;p&gt;We’ve been tuning our development flow so that we can do releases on a shorter schedule and it seems to be working: it’s been 11 weeks since the release of 2.0.&lt;/p&gt;

&lt;p&gt;This new version has many improvements that - not only - make it faster again, but also expand the functionality to offer a more complete experience. We’ve focused on bug fixes with an increased attention to details and also added some new functionality.&lt;/p&gt;

&lt;p&gt;A brief overview of some noteworthy changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You can now specify command line arguments on the Run tab, which enables running/debugging in Eclipse with exactly the same arguments as the in the bug report that one of your users just reported :-). More &lt;a href=&quot;https://github.com/bndtools/bndtools/wiki/Program-Arguments&quot;&gt;details here&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Bndtools will now (by default) generate .gitignore files when you create new Bndtools projects so that you don’t commit derived files. This can be switched of in the Bndtools preferences panel.&lt;/li&gt;
  &lt;li&gt;The JAR viewer now by default opens the manifest file and also remembers the selected file so that when the JAR is updated, it will reload the JAR and select that file again.&lt;/li&gt;
  &lt;li&gt;Bndtools now finally fully supports paths containing whitespace. This was a long standing bug that affected launching from Bndtools. See also the notes below.&lt;/li&gt;
  &lt;li&gt;A compiler error is now generated on incorrect usage of the &lt;code class=&quot;highlighter-rouge&quot;&gt;@Reference&lt;/code&gt; annotation. An example: you have a setter (e.g. add) for a dynamic dependency, but no unsetter (e.g. remove).&lt;/li&gt;
  &lt;li&gt;We again improved the build speed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course there are many more gems in the &lt;a href=&quot;https://github.com/bndtools/bndtools/wiki/Changes-in-2.1.0&quot;&gt;full list of changes&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;important-notes&quot;&gt;Important Notes:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;We’re deprecating running from bnd.bnd files, which is why we’re no longer showing the ‘Run Requirement/Resolve’ panel on the Run tab. Users are strongly advised to migrate their run settings into .bndrun files. Expect the Run tab to be removed completely for bnd.bnd files in a future release.&lt;/li&gt;
  &lt;li&gt;Existing workspaces should update their cnf/buildrepo/biz.aQute.launcher to version 1.0.6 to fix issues with paths containing whitespace. Download it &lt;a href=&quot;https://bndtools.ci.cloudbees.com/job/bnd.master/72/artifact/dist/bundles/biz.aQute.launcher/biz.aQute.launcher-1.0.6.jar&quot;&gt;here&lt;/a&gt;, or generate a new cnf project by removing the existing one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation:&lt;/h2&gt;

&lt;p&gt;You can install Bndtools into Eclipse through the marketplace or use our Eclipse update site, see &lt;a href=&quot;http://bndtools.org/installation.html&quot;&gt;further instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For those of you that want to live on the (bleeding) edge, our latest stable build lives &lt;a href=&quot;https://bndtools.ci.cloudbees.com/job/bndtools.master/lastSuccessfulBuild/artifact/bndtools.build/generated/p2/&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As usual, please report any issues you find on our Github bug tracker: https://github.com/bndtools/bndtools/issues&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Bndtools 2.0 Released</title>
     <link href="http://njbartlett.name/2013/02/11/bndtools2-released.html"/>
     <updated>2013-02-11T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2013/02/11/bndtools2-released</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;After a long and grueling process, I’m pleased (and considerably relieved) to announce that Bndtools 2.0 has been released!&lt;/p&gt;

&lt;p&gt;There are many, many improvements in this release, which I will only summarise below; see the &lt;a href=&quot;http://bndtools.org/whatsnew2-0-0.html&quot;&gt;release notes&lt;/a&gt; for more details. All together I believe that Bndtools is now the foremost tool for developing OSGi applications, and continues our mission to make OSGi development &lt;em&gt;easier&lt;/em&gt; and &lt;em&gt;more productive&lt;/em&gt; than traditional Java development.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Support for OSGi Release 5 Resolver and Repository specifications;&lt;/li&gt;
  &lt;li&gt;Export run descriptors as standalone executables;&lt;/li&gt;
  &lt;li&gt;Baselining (build errors for incorrectly versioned bundles);&lt;/li&gt;
  &lt;li&gt;Enhanced Semantic Versioning, using annotations for Consumer and Provider roles;&lt;/li&gt;
  &lt;li&gt;Exported Package Decorations;&lt;/li&gt;
  &lt;li&gt;Improved Incremental Builder;&lt;/li&gt;
  &lt;li&gt;Support for Apache ACE;&lt;/li&gt;
  &lt;li&gt;Lots and lots of bug fixes and performance improvements (e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;Conditional-Package&lt;/code&gt; processing was sped up over 100 times!).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Version 2.0 has been such a huge release because of the sheer amount of changes introduced in both bnd and in Bndtools. In the future we expect to make incremental releases much more frequently, and this includes a commitment not to change the structure of Bndtools workspaces (or if they need to change, to provide tools that make the migration transparent).&lt;/p&gt;

&lt;p&gt;Bndtools 2.0 is available now on the Eclipse Marketplace. For other installation options refer to the &lt;a href=&quot;http://bndtools.org/installation.html&quot;&gt;installation guide&lt;/a&gt;.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>No Solution for Complexity?</title>
     <link href="http://njbartlett.name/2013/02/04/no-solution-for-complexity.html"/>
     <updated>2013-02-04T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2013/02/04/no-solution-for-complexity</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Yesterday I read a fascinating &lt;a href=&quot;http://www.bbc.co.uk/news/technology-21280943&quot;&gt;article on the BBC News website&lt;/a&gt; about the complexity of banking software. To summarise: last year saw a number of severe IT glitches at banks causing outages in payment processing and other problems, and the article predicts that such glitches will get more common in the future due to increasing sofware complexity.&lt;/p&gt;

&lt;p&gt;Here’s the part that got my attention:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The core of the problem is that the business software used by the institutions has become horrifically complex, according to Lev Lesokhin, strategy chief at New York-based software analysis firm Cast.&lt;/p&gt;

  &lt;p&gt;He says developers are good at building new functions, but bad at ensuring nothing goes wrong when the new software is added to the existing mix.&lt;/p&gt;

  &lt;p&gt;“Modern computer systems are so complicated you would need to perform more tests than there are stars in the sky to be 100% sure there were no problems in the system,” he explains.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sigh.&lt;/p&gt;

&lt;p&gt;If only there were a way to create “firewalls” between different parts of a large system, so that we could be absolutely sure that the functionality within each firewall cannot break merely from adding new functionality outside it. Then we could know precisely the scope of any change, and test only the things that can potentially break rather than the entire universe.&lt;/p&gt;

&lt;p&gt;Of course &lt;em&gt;there is&lt;/em&gt; a way to do this. It’s called &lt;strong&gt;modularity&lt;/strong&gt;. Sadly it’s not very popular because it requires planning and discipline – two words that developers seem to be averse to, even though they pay off handsomely by averting cock-ups in deployment. Also to be fair to the developers, it requires strategic investment in infrastructure, which has been sorely lacking. Businesses always have difficulty justifying measurable up-front costs leading to unknown future gains. So let me tell you a story about real, measurable gains from modularity.&lt;/p&gt;

&lt;p&gt;A few years ago I worked for a manufacturer of medical devices. These were large, powerful machines that could quite easily kill a patient if they were to malfunction. Incidentally, &lt;a href=&quot;https://mmilinkov.wordpress.com/&quot;&gt;Mike Milinkovich&lt;/a&gt; tells a terrifying story about how he was nearly killed by a &lt;a href=&quot;https://en.wikipedia.org/wiki/Therac-25&quot;&gt;software bug&lt;/a&gt;… all things considered I prefer banks; when they go wrong the only thing you lose is money.&lt;/p&gt;

&lt;p&gt;Naturally, the business was heavily regulated. Whenever a module of the system (hardware or software) was changed, it would have to be thoroughly retested, and those tests certified by the regulator. The process was terribly slow and expensive, and it would have to be done not just for the changed module but for all the other modules that could potentially be affected by it. By using a strong modularity solution, the manufacturer could &lt;em&gt;prove&lt;/em&gt; to the regulator that a change in module A could not possibly affect the working of module B, and therefore module B did not need to be retested. The engineering effort required to achieve this was not cheap, but it ultimately saved them millions of dollars and allowed them to bring new features to market quicker.&lt;/p&gt;

&lt;p&gt;Modularity is a technique and a mindset as much as it is a specific technology. Nevertheless there is one technology that is mature, well proven and has stood the test of time: &lt;a href=&quot;http://www.osgi.org/Main/HomePage&quot;&gt;OSGi&lt;/a&gt;. Another quote, this time from &lt;a href=&quot;http://softwaresimplexity.blogspot.co.uk/&quot;&gt;Peter Kriens&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;OSGi … is a messenger that tells you that your code is ugly. In more traditional environments you would have this fuzzy warm feeling that all was ok due to the absence of warnings and errors. The power of OSGi is that it actually allows you to go to a warm and fuzzy place that is not fiction (like all other Java build environments) but based on hard facts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Look it up, and perhaps you could save your bank from making headlines for all the wrong reasons.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>The Dreaded Thread Context Class Loader</title>
     <link href="http://njbartlett.name/2012/10/23/dreaded-thread-context-classloader.html"/>
     <updated>2012-10-23T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2012/10/23/dreaded-thread-context-classloader</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Tomorrow at &lt;a href=&quot;http://www.osgi.org/CommunityEvent2012/HomePage&quot;&gt;OSGi Community Event 2012&lt;/a&gt; I will be talking about &lt;a href=&quot;http://www.eclipsecon.org/europe2012/sessions/how-make-your-code-osgi-friendly-without-depending-osgi&quot;&gt;“How to make your library OSGi friendly without depending on OSGi”&lt;/a&gt;. During this talk I will make reference to Java’s Thread Context Class Loader (TCCL), but since it is only a 25-minute talk I will not have time to go into great detail on this subject. Therefore I thought it would be helpful to write this post with some of the background information.&lt;/p&gt;

&lt;p&gt;Much of the technical information and research in this post is derived from an old, unpublished OSGi RFP authored by Peter Kriens. I have used it with his permission.&lt;/p&gt;

&lt;h2 id=&quot;history&quot;&gt;History&lt;/h2&gt;

&lt;p&gt;The thread context class loader (TCCL) has a very interesting history in Java.&lt;/p&gt;

&lt;p&gt;Java defines a hierarchy of class loaders, and in a typical Java runtime the “application” loader at the bottom is aware of the “classpath” (as supplied via the &lt;code class=&quot;highlighter-rouge&quot;&gt;-classpath/-cp&lt;/code&gt; switch), and the boot loader is aware of the JRE classes in rt.jar etc. There is also an “extension” class loader in the middle, which loads from the JRE &lt;code class=&quot;highlighter-rouge&quot;&gt;ext&lt;/code&gt; directory. Class loaders delegate upwards to their parent, which means the application loader can see any class offered by the boot loader but the boot loader cannot see the application classes.&lt;/p&gt;

&lt;p&gt;Sun first ran into problems with this scheme when implementing Java Serialization, as used in Remote Method Invocation (RMI). Deserializing data from a stream as Java objects required knowledge of the application classes, but the deserialization code was loaded by the boot loader; therefore it would not normally have visibility of the classes. The problem was fixed by adding private native methods to the JRE that would allow inspection of the call stack in order to find the first non-null class loader.&lt;/p&gt;

&lt;p&gt;However, many other extension libraries soon ran into the same problem, and they could not (and should not!) all solve it with private native methods in the Sun JVM. At about the same time, J2EE became very important. J2EE is an application model where the Java code runs in a severely restricted environment. Applications run in a “silo”. Each application runs in a separate class loader and threads may not cross application/silo boundaries. Applications can use the extensions provided by the VM and the libraries provided by the container, but they cannot use any code from each other. This model also suffers from the problem that the libraries provided by the container cannot access the application code.&lt;/p&gt;

&lt;p&gt;Therefore in Java 1.2 the TCCL was introduced: a class loader that is associated with a thread, as a thread-local variable. This means that any libary can at any time access the “current” context loader by asking the calling thread. This context loader is expected to have visibility to the specific application class loader that is responsible for the call, and therefore visibility of the application classes.&lt;/p&gt;

&lt;p&gt;Sun also started to use the TCCL heavily itself, though without proper specification or guidance. The 1.5 JDK has 79 references to &lt;code class=&quot;highlighter-rouge&quot;&gt;Thread.getContextClassLoader()&lt;/code&gt;. Since Java 1.4, the Java VM was modified to use the context class loader in JNDI, JAXP, CORBA, JMX, Xalan, Xerces, AWT, Beans, SQL, Logging, Prefs, RMI, Security, Swing, and most of the XML subsystems. Additionally most middleware libraries like Hibernate, Saxon, Jakarta Commons Logging and many others started to use the TCCL as either the first or last resort. Java has provided virtually no specification or guidelines on the use of TCCL. This has caused almost every library to follow a different strategy.&lt;/p&gt;

&lt;p&gt;The key questions to answer regarding the correct use of TCCL are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;when should it be set, and by whom?&lt;/li&gt;
  &lt;li&gt;of what set of classes should it have visibility?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From a J2EE point of view these questions are relatively easy to answer because the programming model is so constrained. The container owns all the entry points; i.e., it controls the HTTP thread running the Servlets and the RMI sockets for EJBs, creation of additional threads is forbidden, etc) and it can therefore ensure that the TCCL is always set on entry into the application code. Since applications are entirely self-contained, the set of visible classes is simply all classes owned by the application.&lt;/p&gt;

&lt;p&gt;In a modular runtime such as OSGi these questions are far harder to answer. Bundles are free to create their own threads and entry points, and there is no general way to identify the set of bundles that contribute classes for an “application”; indeed, the very concept of an “application” is much harder to pin down. We could constrain the programming model and require that an application be deployed as a single bundle with no dependencies, but this would negate most of the benefits of using OSGi. Therefore OSGi does not attempt to define what the TCCL should be at any particular time, and typically it is left null.&lt;/p&gt;

&lt;h2 id=&quot;alternatives-to-tccl&quot;&gt;Alternatives to TCCL&lt;/h2&gt;

&lt;p&gt;In our own OSGi-compliant code, or in any library with explicit OSGi support, we need not worry about the TCCL, because OSGi Services provide a far cleaner approach than any ClassLoader-based approach to loading extensions. However, legacy third-party libraries are still an issue. Many such libraries attempt to load application classes by name at runtime: for example, Hibernate reads class names from &lt;code class=&quot;highlighter-rouge&quot;&gt;.hbm.xml&lt;/code&gt; files and then creates instances of those classes for each database record.&lt;/p&gt;

&lt;p&gt;When you move such a library to &lt;em&gt;any&lt;/em&gt; kind of modular environment – including OSGi, JBoss Modules or even Jigsaw – you find that it breaks, because the name of a class is not sufficient to uniquely identify it. The identity of a class consists of its fully qualified name AND the class loader that defined it, which in OSGi usually corresponds to the bundle that contains it.
So in addition to the name, we need to know the class loader from which to load the class. Due to the wide variety of class loading environments created by various application servers, many libraries attempt to solve this problem with a set of heuristics. Consulting the TCCL is usually one of the heuristics, along with checking the library’s own class loader, the JRE extension class loader, etc.&lt;/p&gt;

&lt;p&gt;If a library &lt;em&gt;only&lt;/em&gt; consults the TCCL then we are somewhat stuck: we will have to explicitly set the TCCL from our own code before calling into the library. Fortunately this is rarely the case, for example most such libraries will also call &lt;code class=&quot;highlighter-rouge&quot;&gt;Class.forName()&lt;/code&gt;, which means the library will consult its own class loader to load the class. This is still far from ideal, but we can work around it by deploying a single fragment rather than scattering calls to &lt;code class=&quot;highlighter-rouge&quot;&gt;setContextClassLoader()&lt;/code&gt; throughout our code. Far better is when a library eschews class names entirely and allows Class &lt;em&gt;objects&lt;/em&gt; to be passed; or at least offers an API method to set the class loader from which the class names should be loaded.&lt;/p&gt;

&lt;p&gt;Unfortunately it’s very hard to predict in advance – at least without closely inspecting the code – what kind of heuristics the library employs, again because of the complete lack of specification and guidance in this area.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;I hope you will attend my talk tomorrow, which is mainly addressed to authors of Java libraries that want their code to work well in OSGi, but not &lt;em&gt;only&lt;/em&gt; in OSGi. As you can doubtless infer from this blog post, avoiding the TCCL and other weird ClassLoader-based hacks is a big part of being OSGi-friendly, but I will also talk about service dynamics and configuration issues. See you there!&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Jigsaw Postponed</title>
     <link href="http://njbartlett.name/2012/07/19/jigsaw-postponed.html"/>
     <updated>2012-07-19T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2012/07/19/jigsaw-postponed</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;The dust is now settling on the announcement that Jigsaw – the prototype project that was widely expected to become the Java SE 8 Module System – will be deferred to Java 9. This is just the latest delay to a promised feature that started way back in 2005 with JSR 277, was supposed to be delivered in Java 7, then in Java 8, now in Java 9… it’s not unreasonable to ask whether Java Modularity will &lt;em&gt;ever&lt;/em&gt; happen.&lt;/p&gt;

&lt;p&gt;Believe it or not, I am disappointed. It’s true that some in the OSGi community consider the news to be unequivocally a good thing: the removal of a competitor can certainly take the pressure off. However we need pressure to raise our game and continue improving the usability and productivity aspects of working with OSGi. Frankly if Jigsaw could truly do a better job than OSGi then it would deserve to take over.&lt;/p&gt;

&lt;p&gt;The big problem with Jigsaw is not that it competes with OSGi: as currently defined, it does not. The problem is scope creep.&lt;/p&gt;

&lt;p&gt;First an unavoidable fact: whatever module system is used to modularise the JRE itself must be able to run &lt;em&gt;inside&lt;/em&gt; the JRE, i.e. it has to be part of the core. OSGi is a general-purpose module system that is conceptually very simple (export a package, import a package) but due to the nature of real systems it has to handle an awful lot of edge cases. These edge-cases and the OSGi support for them have been built up over around 14 years of putting OSGi into real production systems, but they contribute to the size of a typical OSGi framework (480k for Apache Felix 4.0.3) and to the length of the specification document. In an enterprise application, and even in many modern mobile applications, 480k is nothing to worry about, but it’s still too big for the inner sanctum of the JRE.&lt;/p&gt;

&lt;p&gt;Add to this that the JRE has some very unusual problems that don’t affect normal libraries and applications, and OSGi’s general-purpose module support doesn’t look so useful for JRE modularity. In fact the JRE is almost nothing but a bunch of edge-cases. So there’s a good case for putting a special-purpose module system into the JRE that supports only the JRE requirements… and that’s what Jigsaw was meant to be. Incidentally if you took OSGi and stripped out all the general purpose features, leaving in only features needed for the JRE… you’d get something surprisingly close to Jigsaw!&lt;/p&gt;

&lt;p&gt;Unfortunately as they say, when all you have is a hammer everything looks like a nail. After building themselves a shiny new hammer for the JRE, the Jigsaw developers started to see nothing but nails in the Java application and library space. Once you step into that space though you need the general purpose solution with all the edge-cases. I wasn’t really concerned that Jigsaw was heading to take over this space because it was so clearly deficient, though I was concerned about developers who would waste huge amounts of time and money trying to get it to work. (Incidentally I have been accused of opposing Jigsaw for selfish reasons, since I make most of my living from OSGi. On the contrary: in fact I’m confident that Jigsaw would double my consulting rates, since so many people will need rescuing from tangled messes. That’s just not how I &lt;em&gt;want&lt;/em&gt; to make a living.)&lt;/p&gt;

&lt;p&gt;So because of this scope creep it looks like we will not get the benefits of a modular JRE until at least 2015. This is a great shame for developers using OSGi just as it is for everyone else developing on the Java platform. For starters, who wouldn’t like to have the ability to strip down the JRE to just the core functionality that we need?? Also the way OSGi interacts with the JRE today leaves a lot to be desired.  Ideally an OSGi bundle wants to depend entirely on versioned packages, but due to a JVM security restriction we have to treat the entire &lt;code class=&quot;highlighter-rouge&quot;&gt;java.*&lt;/code&gt; namespace differently. The best we can do is use the &lt;code class=&quot;highlighter-rouge&quot;&gt;Bundle-RequiredExecutionEnvironment&lt;/code&gt; header to assert the version of Java our bundle requires, i.e. Java 5 or Java 6 etc. This kind of works but is a very blunt tool. Another problem is that the other packages from the JRE – &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.swing&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;org.w3c.dom&lt;/code&gt; etc – are all completely unversioned. Then you have garbage like the inclusion of package &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.transaction&lt;/code&gt; since Java 1.3, but only a small subset of the classes that belong in that package… this sounds like a trivial thing but it breaks an amazing number of libraries.&lt;/p&gt;

&lt;p&gt;A modular JRE could have fixed these problems, allowing OSGi bundles to require a JRE containing a specified set of versioned modules. We could then perform compile-time validation that only the required APIs were actually used within the bundle, and we could even use the OSGi R5 Resolver to work out which set of JRE modules to install when provisioning that bundle. I do still hope we can get to this point in the future.&lt;/p&gt;

&lt;p&gt;In conclusion I have a message to the OSGi community: &lt;strong&gt;this is not the time to sit on our laurels&lt;/strong&gt;. Yes, we are the only realistic solution today for Java modularity, and we have just been given some extra time to consolidate our lead. However OSGi is still not as easily usable or as productive as it should be – if we don’t address these issues &lt;em&gt;now&lt;/em&gt;, then we deserve to be forgotten after Java 9.&lt;/p&gt;

</content>
   </entry>
 
   <entry>
     <title>Are We There Yet?</title>
     <link href="http://njbartlett.name/2012/03/21/are-we-there-yet.html"/>
     <updated>2012-03-21T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2012/03/21/are-we-there-yet</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Peter &lt;a href=&quot;http://www.osgi.org/blog/2012/03/coordinator.html&quot;&gt;wrote a blog post&lt;/a&gt; yesterday about the OSGi Coordinator service, which is new in the R4.3 Compendium. I wanted to give a more concrete example of how it is used.&lt;/p&gt;

&lt;p&gt;Sometimes we want to perform an expensive operation after a bunch of things have changed. For example, in the writable OBR repositories used by &lt;a href=&quot;http://bndtools.org/&quot;&gt;Bndtools&lt;/a&gt; we need to regenerate the index XML file after the user deploys a new resource into the repository. However, what if the user is deploying a hundred resources? It would be wasteful to regenerate the index after each of those deployments, because 99 times out of the hundred we will throw away the result.&lt;/p&gt;

&lt;p&gt;The Coordinator service is therefore used as a way of chunking operations. When deploying a file to the repository, we check if a coordination is ongoing; if one is, then we join it and defer the regeneration of the index. Otherwise, we just regenerate the index immediately.&lt;/p&gt;

&lt;p&gt;Here is the abbreviated code for &lt;code class=&quot;highlighter-rouge&quot;&gt;put()&lt;/code&gt;, i.e. the method that does the deployment:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Jar&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;storageRepo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;newFilesInCoordination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newFile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coordinator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coordinator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addParticipant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;finishPut&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newFile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;When the coordinator service exists AND there is a current coordination, indicated by &lt;code class=&quot;highlighter-rouge&quot;&gt;addParticipant&lt;/code&gt; returning &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt;, we simply begin the put operation and remember the file that we have created in the context of this coordination. However when there is no coordinator or current coordination, we both begin and immediately finish the put operation. The &lt;code class=&quot;highlighter-rouge&quot;&gt;finishPut&lt;/code&gt; method looks like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;finishPut&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;regenerateIndex&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;newFilesInCoordination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In order to join the coordination we have to implement the &lt;code class=&quot;highlighter-rouge&quot;&gt;Participant&lt;/code&gt; interface, which has two methods &lt;code class=&quot;highlighter-rouge&quot;&gt;ended&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;failed&lt;/code&gt;. The &lt;code class=&quot;highlighter-rouge&quot;&gt;ended&lt;/code&gt; method is very simple, we just call &lt;code class=&quot;highlighter-rouge&quot;&gt;finishPut&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ended&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Coordination&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coordination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;finishPut&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In the &lt;code class=&quot;highlighter-rouge&quot;&gt;failed&lt;/code&gt; method we clean up the changes that we started to make. The repository will be back in the state it was in before the &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt; method was called:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;failed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Coordination&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coordination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newFilesInCoordination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// omitted some extra error handling and logging here&lt;/span&gt;
	&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;newFilesInCoordination&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The thing I like about Coordinator is that it provides a very useful optimisation, but things can still work without it. In this case, when there is no Coordinator service available the repository regenerates the index on every &lt;code class=&quot;highlighter-rouge&quot;&gt;put&lt;/code&gt;… which is exactly the behaviour that it had before I added Coordination support. Simply by adding a Coordinator bundle I can improve the performance of bulk repository updates.&lt;/p&gt;

&lt;p&gt;There is a Coordinator implementation &lt;a href=&quot;http://download.eclipse.org/equinox/drops/S-3.8M6-201203141800/download.php?dropFile=org.eclipse.equinox.coordinator_1.1.0.v20120219-1616.jar&quot;&gt;available in Equinox 3.8M6&lt;/a&gt;. As far as I know Felix does not have its own implementation yet, but the Equinox Coordinator works fine on Felix in my testing.&lt;/p&gt;

&lt;p&gt;Incidentally, the use-cases for the Coordinator may remind you of the archetypal chunking problem in OSGi: when should the framework resolve bundles after a series of install, update and uninstall operations? Bundle resolution is not merely expensive but may actually produce spurious errors if done at inappropriate times, so the OSGi framework has always had the ability to chunk these operations: we call &lt;code class=&quot;highlighter-rouge&quot;&gt;FrameworkWiring.refreshBundles&lt;/code&gt; method (or &lt;code class=&quot;highlighter-rouge&quot;&gt;PackageAdmin.refreshPackages()&lt;/code&gt; prior to R4.3) to signal when we are done. The Coordinator service generalises this idea to make it available for our own applications.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Free OSGi BOF at DevCon 2012</title>
     <link href="http://njbartlett.name/2012/01/12/osgi-devcon-bof.html"/>
     <updated>2012-01-12T12:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2012/01/12/osgi-devcon-bof</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;The programme for the Birds-of-a-Feather (BOF) session at OSGi DevCon 2012 – co-hosted with EclipseCon 2012 – has been &lt;a href=&quot;https://www.osgi.org/DevCon2012/HomePage#bof&quot;&gt;announced&lt;/a&gt;. I will be speaking about the Java 8 module system, Jigsaw and how they relate to OSGi: what are the differences; the pros and cons of each in different environments; and the potential for them to work together.&lt;/p&gt;

&lt;p&gt;There will also be sessions on: OSGi Subsystems; simplifying development with the upcoming OSGi Bundle Repository (OBR) standard; and finally a surprise session from a mystery speaker.&lt;/p&gt;

&lt;p&gt;The BOF is free to attend, you don’t need to be registered for OSGi DevCon/EclipseCon. So if you’re in the Washington DC area and interested in learning more about OSGi or meeting several of the top OSGi experts… you know where to go.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2012devcon_bof.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>OSGi Training in 2012; London, NY, DC and Sydney</title>
     <link href="http://njbartlett.name/2012/01/11/osgi-trainings.html"/>
     <updated>2012-01-11T18:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2012/01/11/osgi-trainings</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;I will be running a series of &lt;a href=&quot;http://bndtools.org/training.html&quot;&gt;OSGi training courses&lt;/a&gt; this year, with the first two being held in London and New York in February. The early bird pricing for London will expire in the next couple of days, so please do hurry to secure your place!&lt;/p&gt;

&lt;p&gt;If you’re in North America and can’t make NY in February then there will be another chance to take the training in the Washington DC area (very close to Dulles airport). Then later in the year I will be down in Sydney, Australia.&lt;/p&gt;

&lt;p&gt;You might be wondering about the “Masterclass in OSGi” series that I previously ran with Peter Kriens, who recently &lt;a href=&quot;http://www.osgi.org/blog/2012/01/moving-on.html&quot;&gt;announced&lt;/a&gt; his resignation from the OSGi Alliance. Peter is very busy completing his duties for the Alliance and then will be fully engaged with his next venture, so he has told me that he is not able to participate in the masterclasses for the foreseeable future.&lt;/p&gt;

&lt;p&gt;My new course is heavily based on the subjects and discussions that arose from the masterclasses that took place in 2010/11, though it is intended to be more accessible for OSGi beginners. I still believe it’s the absolute best way to quickly achieve a deep understanding and mastery of OSGi and modularity in Java, and I very much look forward to seeing you there.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Eclipse Dock Icons on Mac OS X</title>
     <link href="http://njbartlett.name/2011/10/09/workspace-mac-badge.html"/>
     <updated>2011-10-09T18:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/10/09/workspace-mac-badge</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;If you’re a heavy Eclipse user on Mac OS, you’re probably just as sick as I am of seeing the following in your Dock:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/macbadge/dock.png&quot; alt=&quot;Dock&quot; /&gt;&lt;/p&gt;

&lt;p&gt;…  and the following in your Application Switcher:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/macbadge/switcher.png&quot; alt=&quot;Switcher&quot; /&gt;&lt;/p&gt;

&lt;p&gt;How on Earth am I supposed to keep track of all those icons?? Well I &lt;strong&gt;just can’t&lt;/strong&gt;, and I’ve been struggling with this nonsense for years. I’ve tried changing the Dock icon, and the name of the application, but these settings are still shared by all the workspaces that run with that copy of Eclipse.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enough is enough&lt;/strong&gt;, I need a per-workspace label for my dock icons, so I created a plug-in that I’m calling the &lt;em&gt;Workspace Badge Plug-in for Mac OS&lt;/em&gt;. It looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/macbadge/dock_after.png&quot; alt=&quot;Dock&quot; /&gt;&lt;/p&gt;

&lt;p&gt;… and this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/macbadge/switcher_after.png&quot; alt=&quot;Switcher&quot; /&gt;&lt;/p&gt;

&lt;p&gt;By default it uses the last segment of your workspace path, but there isn’t much space so that often gets shortened with ellipses. So you can set your own short string in the workspace using a preference page:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/macbadge/prefpage.png&quot; alt=&quot;Preference Page&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The amazing thing is, this is probably the tiniest plug-in I have ever written for Eclipse, and is likely to be one of the most useful! If you want to try it out, install from the following update site URL (Marketplace listing coming soon):&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;http://macbadge-updates.s3.amazonaws.com/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The plug-in has not been exhaustively tested. It works for me on Eclipse 3.7 Indigo. I have no idea what would happen – and take no responsibility for what &lt;em&gt;might&lt;/em&gt; happen – if you try to install it on an OS that is not Mac OS.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Why OBR?</title>
     <link href="http://njbartlett.name/2011/09/12/why-obr.html"/>
     <updated>2011-09-12T11:45:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/09/12/why-obr</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Pascal Rapicault has written a &lt;a href=&quot;http://lenettoyeur-on-eclipse.blogspot.com/2011/09/why-not-obr.html&quot;&gt;blog post&lt;/a&gt; on his reasons for not choosing OBR as the provisioning technology for Eclipse.&lt;/p&gt;

&lt;p&gt;I have absolutely no wish to start a fight, certainly not between myself and Pascal whom I regard as a friend. However it would be remiss not to correct the errors in his post, because that could leave the impression that OBR is an unworkable technology. The fact is that, today, both OBR and p2 are workable technologies for provisioning OSGi applications, but I would argue that OBR is cleaner and more usable, and &lt;strong&gt;much&lt;/strong&gt; easier to integrate. That’s why I am incorporating OBR support into &lt;a href=&quot;http://bndtools.org/&quot;&gt;Bndtools&lt;/a&gt; at pretty much every level.&lt;/p&gt;

&lt;p&gt;The OSGi Bundle Repository draft specification defines a repository index format and a resolver API. It allows us to do the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Add a repository index (or multiple indexes) to a resolver.&lt;/li&gt;
  &lt;li&gt;Specify the starting environment, for example which platform, which Java version, etc.&lt;/li&gt;
  &lt;li&gt;Add a set of requirements: what we want to get out of the resolver.&lt;/li&gt;
  &lt;li&gt;The resolver calculates the set of required resources that will satisfy those requirements. It also reports optional resources that may enhance the functionality of the selected set.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To address Pascal’s arguments in turn:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;OBR focus was bundle centric. No “group” (aka features), no native files, …&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Incorrect. An OBR repository can reference any kind of resource. The dependencies between resources are modelled as abstract “requirements” and “capabilities”. So a group/feature can be modelled as a resource that requires a bunch of other resources using their “name” capability.&lt;/p&gt;

&lt;p&gt;Naturally, most extant OBR repositories overwhelmingly contain OSGi bundles, but the same is true of p2.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The repository format was fixed and was XML only, no possibility of extension.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes the repository format is XML, but it is quite extensible thanks to the generic requirement/capabilities model.&lt;/p&gt;

&lt;p&gt;OBR’s format has the advantage of being a single file, &lt;code class=&quot;highlighter-rouge&quot;&gt;repository.xml&lt;/code&gt;, compared to p2’s twin files &lt;code class=&quot;highlighter-rouge&quot;&gt;content.xml&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;artifacts.xml&lt;/code&gt;, and it is more readable than either of them.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Each bundle listed in the repository was referring to the payload (the actual jar for the bundle) using a fix URL rather than abstracting the artifact location in a coordinate – like Maven does with its concept of GAV or like p2 does with “artifact keys” – which makes mirroring just plain painful (I know it is possible to provide URL handlers, but come on…).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Incorrect. OBR repository indexes use URIs, not URLs. It is up to the downloader to resolve those to a physical location, just as p2’s downloader must resolve its abstract “coordinates”. Mirroring is therefore perfectly possible. Indeed there is no functional difference between a URI and a Maven “coordinate”, and Maven coordinates can be trivially encoded as URIs.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The provided API was not allowing for transactional state change (some bundles could be installed, but not all the required ones if the download failed).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;OBR does not specify &lt;strong&gt;how&lt;/strong&gt; to download resources, it only calculates &lt;strong&gt;which&lt;/strong&gt; resources are required to satisfy the question we asked of it. Transactional behaviour can be built into the code that we use to download those resources. So while this was missing from OBR when Pascal evaluated it, he could have chosen to implement a transactional downloader on top of OBR rather than redesigning the whole repository and resolver.&lt;/p&gt;

&lt;p&gt;Since it is a standards document, OBR avoids mandating implementation details such as how to download resources, because whatever is convenient for Eclipse may be inconvenient or impossible in other environments.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The metadata did not accommodate the expression of what needed to happen to the bundle (e.g. should it be started, set the start level, etc.) and thus even less to other things.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;State requirements – e.g. the requirement for the bundle to be in active state – can again be represented in the requirements/capabilities model. However it is admittedly non-obvious how to do this, and the latest (non-released) draft of the specification will make this area clearer.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The resolver always insisted on installing all the fragments available (which in complex repos like Indigo means that installing JDT will bring in parts of WindowBuilder since it has some fragment to JDT UI iirc)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The resolver tells us about available OSGi fragments as optional resources. The UI for a resolver (e.g. Eclipse Update Manager) should present those optional resources to the user and allow some or none of them to be selected.&lt;/p&gt;

&lt;p&gt;Platform-specific fragments (e.g. SWT) can use the requirements/capabilities model to ensure they are not selected on an incorrect platform. For example, the Win32 SWT fragment would have a requirement of type &lt;code class=&quot;highlighter-rouge&quot;&gt;platform&lt;/code&gt; and filter value &lt;code class=&quot;highlighter-rouge&quot;&gt;(&amp;amp;(os=win32)(ws=win32)(arch=x86))&lt;/code&gt;. Before running the resolver we would add a “global” capability for the platform we actually want to resolve on.&lt;/p&gt;

&lt;h2 id=&quot;why-not-p2&quot;&gt;Why not p2?&lt;/h2&gt;

&lt;p&gt;Almost nobody believes that p2 was ready to be released when it actually was released, back in Eclipse 3.4 (Ganymede). As a result, installation of plug-ins in Ganymede, and even in the following release (3.5 Galileo) was so error-prone that most Eclipse users reverted to unzipping files directly into their &lt;code class=&quot;highlighter-rouge&quot;&gt;plugins&lt;/code&gt; directories.&lt;/p&gt;

&lt;p&gt;P2 finally became sort-of usable in 3.6 (Helios), but it still does not support one of the most important aspects of OSGi resolution: &lt;a href=&quot;/2011/02/09/uses-constraints.html&quot;&gt;uses constraints&lt;/a&gt;. That is, the p2 metadata do not support expression of uses-constraints and the resolver algorithm does not take account of them. As a result it is quite easy to get p2 to resolve a set of bundles but later find that those bundles cannot work in the actual OSGi framework.&lt;/p&gt;

&lt;p&gt;Uses constraints are fully supported by OBR. It is still theoretically possible to generate a resolution set that does not resolve in OSGi, but this will always be possible unless we use the actual OSGi resolver itself, and under identical conditions. In practice, I have found OBR always produces high quality resolution sets so long as I feed it an accurate set of initial capabilities – in other words, GIGO.&lt;/p&gt;

&lt;p&gt;The repository index generator for OBR is a simple command line tool provided in a single small JAR, which can also be used from ANT and Maven (it is already embedded in the Maven Bundle Plugin). In contrast, the p2 generator tool is an ANT task that only runs embedded inside Eclipse. This necessitates firing up a headless Eclipse application from an enclosing ANT build… and naturally you have to have a full Eclipse installation on your build machine.&lt;/p&gt;

&lt;p&gt;Finally, last time I checked, the p2 resolver only ran on Equinox, not on any other OSGi framework.&lt;/p&gt;

&lt;p&gt;On the other hand, there are certainly some valuable contributions in p2. The downloading, transactional updates, touchpoints etc would all still be useful in a provisioning system built on top of OBR’s repository and resolver.&lt;/p&gt;

&lt;h2 id=&quot;the-future&quot;&gt;The Future&lt;/h2&gt;

&lt;p&gt;Pascal is right to try to identify missing features in OBR, but I feel that he fell into the trap of mistaking one particular implementation – the Felix OBR bundle as it existed back in 2007/8 – with the abstract features of the specification itself. All of the requirements he states could have been implemented alongside an improved OBR bundle rather than throwing out the baby with the bathwater&lt;/p&gt;

&lt;p&gt;However, what’s done is done. I’m glad that Pascal has participated in the effort to update the OBR specification, and I hear from my contacts inside the Alliance that the new specification is close to release. At that point I will incorporate the new OBR into Bndtools, and continue to recommend it to my clients who are seeking an OSGi provisioning story.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Solving OSGi "Uses" Constraint Violations</title>
     <link href="http://njbartlett.name/2011/09/02/uses-constraints.html"/>
     <updated>2011-09-02T21:45:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/09/02/uses-constraints</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;One of the thornier deployment problems we sometimes come across in OSGi is the dreaded “uses constraint violation”. I recently helped a client to solve one of these, and it occurred to me to document the problem and the approach to solving it.&lt;/p&gt;

&lt;p&gt;Be warned that this post is quite long and boring. You may not want to read it all right now, but perhaps Google will bring you back here when you first encounter a uses-constraint violation in the wild.&lt;/p&gt;

&lt;h2 id=&quot;what-is-a-uses-constraint-anyway&quot;&gt;What is a Uses Constraint Anyway??&lt;/h2&gt;

&lt;p&gt;You may have already read &lt;a href=&quot;http://blog.springsource.com/2008/10/20/understanding-the-osgi-uses-directive/&quot;&gt;Glyn Normington’s excellent article&lt;/a&gt;, which goes into quite a bit of depth on the subject, but regretably without the assistance of pretty pictures, so if you are a visual thinker like me then you might find the following explanation more accessible.&lt;/p&gt;

&lt;p&gt;Starting with the basics, in OSGi we have dependencies based on Java packages. Some bundle exports a package, possibly with a version number, and another bundle imports it, possibly specifying an acceptable range of versions:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/usesconstraint/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This notation is borrowed from the OSGi specification: a black rectangle is an export and a white rectangle is an import. The surrounding yellow blobs are bundles. The line between the export and the import means that OSGi has chosen that specific export as a match for the import – they have been “wired” together. So B imports package foo (version 1.0) from A.&lt;/p&gt;

&lt;p&gt;Let’s build this up. Suppose bundle B, in addition to importing package foo 1.0, also exports package bar (the version of bar is unimportant). The C bundle imports package bar and gets wired to B:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/usesconstraint/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So far so good. Now let’s complicate things a bit more: let’s say that bundle C, in addition to importing package bar, also imports package foo… BUT it imports version 2.0. Wait, we don’t have foo version 2.0! Never fear, there’s another bundle that does export foo 2.0. We’ll call him D:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/usesconstraint/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Are you surprised that this works? Perhaps not, you may have heard that OSGi supports multiple versions of the same library at the same time, and here it is in action. However there are limits: while we can have multiple versions of the foo package, we must still be able to construct a consistent “class space” for each bundle that has exactly one version of every class. The “class space” for bundle C is shown by the shaded blue area:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/usesconstraint/4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Notice how the shaded area avoids the import of foo inside bundle B. This is only possible if the package bar exported by B &lt;del&gt;has no internal dependency on foo&lt;/del&gt; does not “expose” foo via its signature (thanks to BJ for this correction).&lt;/p&gt;

&lt;p&gt;Exposing foo means that a type in foo is visible through the signature of a type in bar, for example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kn&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;foo.Foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Bar&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// exposure via subclassing&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// exposure via method return type&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setFoo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// exposure via method parameter&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If package bar &lt;em&gt;does&lt;/em&gt; expose package foo, as in this example, then we have a “uses constraint”. We illustrate this with a little rubber band, like so:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/usesconstraint/5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now bundle C cannot be resolved. The rubber band means we cannot exclude the import of foo 1.0 from the blue shaded area, i.e. C’s class space must contain foo 1.0. But it is not allowed to contain both foo 1.0 and foo 2.0, so C’s second import cannot be satisfied.&lt;/p&gt;

&lt;p&gt;I hope this is clear enough, but I’m sure you’re wondering: how the hell do I fix this? We should certainly avoid tempting runtime options that turn off the uses constraint validation. Neither should we start mucking about trying to “fix” the manifests of third-party bundles. Both of these are hacks that only mask the problem. After all, package bar in bundle B really does depend on a specific version of foo, so we shouldn’t blindly force it to use a different version.&lt;/p&gt;

&lt;p&gt;In this example the proper solution is to find an alternative provider of the bar package, one that is compatible with foo 2.0. For example maybe there is a bar version 2.0 available somewhere, that happens to be compatible with foo 2.0. We may need to change the import in bundle C to make sure it gets bar 2.0. If bundle C is our own bundle then this is a reasonable change to make.&lt;/p&gt;

&lt;h2 id=&quot;how-about-a-real-example&quot;&gt;How About a Real Example?&lt;/h2&gt;

&lt;p&gt;Good idea! Let’s move away from foos and bars and look at a real uses-constraint problem. We’ll take the specific example of the client I mentioned: he was trying to use Apache ActiveMQ from an Eclipse RCP application. In the RCP application bundle there was a single import of the &lt;code class=&quot;highlighter-rouge&quot;&gt;org.apache.activemq&lt;/code&gt; package. At runtime the RCP bundle failed to resolve with the following error:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;!MESSAGE Bundle org.example.rcp.activemq_1.0.0.qualifier [37]
was not resolved.
!SUBENTRY 2 org.example.rcp.activemq 2 0 2011-02-08 14:45:37.513
!MESSAGE Package uses conflict: Import-Package: org.apache.
activemq; version=&quot;5.4.2&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here we see the most frustrating aspect of uses-constraint violations: the almost total lack of information about the cause of the problem! We need to put our detective hat on.&lt;/p&gt;

&lt;p&gt;Our bundle, &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.rcp.activemq&lt;/code&gt;, is failing to resolve because it cannot import package &lt;code class=&quot;highlighter-rouge&quot;&gt;org.apache.activemq&lt;/code&gt; version 5.4.2. That package exists, it is exported by bundle number 33, &lt;code class=&quot;highlighter-rouge&quot;&gt;org.apache.activemq.activemq-core&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;osgi&amp;gt; packages org.apache.activemq
org.apache.activemq; version=&quot;5.4.2&quot;&amp;lt;org.apache.activemq.activemq
-core_5.4.2 [33]&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The uses constraint violation tells us that something &lt;em&gt;used by&lt;/em&gt; the package &lt;code class=&quot;highlighter-rouge&quot;&gt;org.apache.activemq&lt;/code&gt; clashes with something else that is imported into our bundle. We can look at the imports of the ActiveMQ bundle:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;osgi&amp;gt; bundle 33
...
Imported packages
  javax.annotation; version=&quot;1.0.0&quot;&amp;lt;com.springsource.javax.annotation...
  javax.jms; version=&quot;1.1.0&quot;&amp;lt;org.apache.geronimo.specs.geronimo-jms_...
  javax.management; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_3.6.1.R36x_...
  javax.management.j2ee.statistics; version=&quot;1.1.0&quot;
       &amp;lt;org.apache.geronimo.specs.geronimo-j2ee-management_1.1_...
  javax.management.openmbean; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.management.remote; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.naming; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.naming.directory; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.naming.event; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.naming.spi; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.net; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.net.ssl; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.security.auth; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.security.auth.callback; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.security.auth.login; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.security.auth.spi; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.sql; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.transaction.xa; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.xml.parsers; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  org.apache.commons.logging; version=&quot;1.1.1&quot;&amp;lt;jcl.over.slf4j...
  org.apache.kahadb.index; version=&quot;5.4.2&quot;
       &amp;lt;org.apache.activemq.kahadb_5.4.2 [30]&amp;gt;
  org.apache.kahadb.journal; version=&quot;5.4.2&quot;
       &amp;lt;org.apache.activemq.kahadb_5.4.2 [30]&amp;gt;
  org.apache.kahadb.page; version=&quot;5.4.2&quot;
       &amp;lt;org.apache.activemq.kahadb_5.4.2 [30]&amp;gt;
  org.apache.kahadb.util; version=&quot;5.4.2&quot;
       &amp;lt;org.apache.activemq.kahadb_5.4.2 [30]&amp;gt;
  org.osgi.framework; version=&quot;1.5.0&quot;&amp;lt;org.eclipse.osgi_...
  org.w3c.dom; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  org.xml.sax; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  org.w3c.dom.traversal; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
  javax.xml.stream; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_...
...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Wow, quite a long list, and I’ve not even included the optional imports! In the worst case we need to review all of these, and then possibly the transitive dependencies of the bundles that export those packages, in order to find the conflict. Nightmare! Fortunately there is a shortcut we can take.&lt;/p&gt;

&lt;p&gt;Recall the conflict in the simplistic example arose because there were two versions of the foo package available. This is a necessary precondition for a uses constraint violation, and it gives us a really big clue:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Look for packages that have more than one exporter.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’d like to be able to say that I jumped straight to the answer at this point, but truthfully I hummed and hawwed a bit first (oh well, it was billable time). I speculated that there might be two copies of the Commons Logging APIs, so I asked the OSGi shell:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;osgi&amp;gt; packages org.apache.commons.logging
org.apache.commons.logging; version=&quot;1.1.1&quot;&amp;lt;jcl.over.slf4j_1.6.1 [31]&amp;gt;
  org.apache.activemq.kahadb_5.4.2 [30] imports
  org.apache.activemq.activemq-core_5.4.2 [33] imports&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Nope, just one export, and it’s imported by both &lt;code class=&quot;highlighter-rouge&quot;&gt;org.apache.activemq.kahadb&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;org.apache.activemq.activemq-core&lt;/code&gt;. No problem there.&lt;/p&gt;

&lt;p&gt;Then I realised: we’re running on Java 6! That’s significant because Java 6 gratuitously added a bunch of APIs to the base JRE library… APIs that were previously available as optional libraries. This is a rich seam of duplication! So my next guess was &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.xml.stream&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;javax.xml.stream; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_3.6.1.R36x_... [0]&amp;gt;
  org.eclipse.ui_3.6.1.M20100826-1330 [2] imports
  org.eclipse.core.expressions_3.4.200.v20100505 [7] imports
  org.eclipse.ui.workbench_3.6.1.M20100826-1330 [10] imports
  org.eclipse.core.runtime_3.6.0.v20100505 [11] imports
  org.eclipse.help_3.5.0.v20100524 [23] imports
  org.apache.activemq.activemq-core_5.4.2 [33] imports&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Again no. Cutting to the chase, the culprit was &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.annotation&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;javax.annotation; version=&quot;0.0.0&quot;&amp;lt;org.eclipse.osgi_3.6.1.R36x_... [0]&amp;gt;
  org.eclipse.ui_3.6.1.M20100826-1330 [2] imports
  org.eclipse.core.expressions_3.4.200.v20100505 [7] imports
  org.eclipse.ui.workbench_3.6.1.M20100826-1330 [10] imports
  org.eclipse.core.runtime_3.6.0.v20100505 [11] imports
  org.eclipse.help_3.5.0.v20100524 [23] imports
javax.annotation; version=&quot;1.0.0&quot;&amp;lt;com.springsource.javax.annotation &amp;gt;
  org.apache.activemq.activemq-core_5.4.2 [33] imports&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Bingo! The package is exported by two bundles: the first is the system bundle itself, which is responsible for exporting all the JRE packages (aside from &lt;code class=&quot;highlighter-rouge&quot;&gt;java.*&lt;/code&gt;), and this version is being imported by all the Eclipse plug-ins.&lt;/p&gt;

&lt;p&gt;The other version is exported by &lt;code class=&quot;highlighter-rouge&quot;&gt;com.springsource.javax.annotation&lt;/code&gt;, which is one of the wrapper bundles available from the &lt;a href=&quot;https://ebr.springsource.com/repository/app/&quot;&gt;repository&lt;/a&gt; hosted by SpringSource. Our RCP application naturally depends on the Eclipse stuff, therefore it cannot get the ActiveMQ library because of this conflict. Time for another pretty diagram:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/usesconstraint/6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-can-this-be-fixed&quot;&gt;How Can This Be Fixed?&lt;/h2&gt;

&lt;p&gt;Another fine question! In our abstract foo/bar case the solution involved finding a provider of “bar” that was compatible with foo version 2.0.0, and then changing our bundle C to make sure it used that new “bar”. In this case, both ActiveMQ and the Eclipse bundle are third-party binaries that we should not change.&lt;/p&gt;

&lt;p&gt;Our goal is to make both ActiveMQ and Eclipse import the same version. ActiveMQ cannot import version 0.0.0 from the JRE, but Eclipse can import version 1.0.0.&lt;/p&gt;

&lt;p&gt;But wait a moment, there is no such thing as version 0.0.0 of &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.annotation&lt;/code&gt;! It’s nonsense. The OSGi system bundle’s job is to export all of the JRE packages but it has no idea what version numbers to use for those exports. Indeed, &lt;strong&gt;nobody&lt;/strong&gt; knows what the version numbers of all the JRE packages are. There is documentation for some of them, but none of that documentation is normative, and anyway it doesn’t cover everything in the JRE. We really need a JSR or OSGi specification that tells us definitively. Anyhow because of the lack of information, the OSGi framework clumsily exports everything as version 0.0.0.&lt;/p&gt;

&lt;p&gt;Therefore the solution involves configuring the OSGi framework in one of the following ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Removing &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.annotation&lt;/code&gt; from the exports of the system bundle altogether; this will make both ActiveMQ and Eclipse resolve from the SpringSource bundle.&lt;/li&gt;
  &lt;li&gt;Exporting the &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.annotation&lt;/code&gt; package from the system bundle as version 1.0.0; then we don’t need the SpringSource bundle.&lt;/li&gt;
  &lt;li&gt;Using a special bundle that pulls the &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.annotation&lt;/code&gt; package from the JRE (using Require-Bundle!) and reexports it as version 1.0.0.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first two approaches require us to create a “profile”, i.e. a list of JRE packages, and pass it to Equinox using the &lt;code class=&quot;highlighter-rouge&quot;&gt;osgi.java.profile&lt;/code&gt; configuration setting.&lt;/p&gt;

&lt;p&gt;The third approach is quite tricky if we have to create the bundle ourselves, but there is an existing bundle in most Eclipse IDE distributions that does exactly this. Unfortunately the bundle doesn’t appear in the RCP target platform downloads, which is why my client went to the SpringSource bundle repository to find a provider for the package and ended up in the mess he was in.&lt;/p&gt;

&lt;p&gt;What’s my recommendation? Really I prefer the second option because the third just feels like a hack to me. There is a further issue though: if you use Eclipse PDE and click the “Validate Plug-ins” button in the Run Configuration dialog, then PDE will report a missing import, because it doesn’t know about the JRE profile setting. Clearly a missing feature or even a bug in PDE, but because of this you may prefer the third option.&lt;/p&gt;

&lt;h2 id=&quot;another-rant-about-require-bundle&quot;&gt;Another Rant About Require-Bundle&lt;/h2&gt;

&lt;p&gt;Notice the arrows in the previous diagram, they indicate a Require-Bundle dependency rather than an import/export wiring. It turns out that Require-Bundle is responsible for this uses constraint problem, so I might as well have another rant about it.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;packages&lt;/code&gt; command told us that &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.annotation&lt;/code&gt; from the JRE was imported by Eclipse core runtime, core expressions, UI, workbench, and help. But I happen to know that &lt;strong&gt;none of those bundles actually use the &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.annotation&lt;/code&gt; package!!&lt;/strong&gt; I know this because Eclipse still runs on Java 1.4, where those annotation classes won’t even load. But Eclipse uses Require-Bundle as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;Require-Bundle: org.eclipse.osgi&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;By requiring the system bundle, Eclipse implicitly imports the entire JRE. This is a terrible idea, and it is only done in Eclipse because of backward compatibility and because the PDE tooling is so inadequate for working with Import-Package dependencies.&lt;/p&gt;

&lt;p&gt;(In fact, the uses constraint problem in this example can be solved by switching the RCP plug-in to use Import-Package to get hold of its dependencies on the Eclipse APIs. Sadly PDE makes Require-Bundle &lt;strong&gt;so&lt;/strong&gt; convenient, and Import-Package so inconvenient, that very users are disciplined enough. I admit that even I use it when I’m feeling lazy.)&lt;/p&gt;

&lt;p&gt;In my opinion Eclipse 4 should be used as an opportunity to break with the uglier parts of Eclipse’s legacy. It’s admittedly hard to do that when you have an ecosystem of literally thousands of 3rd party plug-ins that would stop running on the new version… but must this crap really be maintained forever? Will Eclipse 5 make the break, or Eclipse 6? A big part of what ails Java itself is the legacy compatibility burden; I hope Eclipse can be bolder.&lt;/p&gt;

&lt;p&gt;Anyway, ranting over, here comes the recommendation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eradicate Require-Bundle dependencies from your bundles.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;installation-order&quot;&gt;Installation Order&lt;/h2&gt;

&lt;p&gt;Consider the following modification to the original abstract scenario. Bundle B now accepts a range for the foo package: either version 1 &lt;strong&gt;or&lt;/strong&gt; 2. If these bundles are all installed at the same time, then C is now resolvable because both C and B can wire to the version 2.0 foo offered by bundle D:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/usesconstraint/7.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In this scenario bundle A will be ignored. However now suppose that only bundles A and B are available at startup, with C and D being installed later.&lt;/p&gt;

&lt;p&gt;At startup B will resolve to the single version of foo available, which is version 1.0.0 from bundle A. When C and D are installed, C will be unresolvable, since it cannot import bar from B at the same time as it imports foo from D. OSGi tries to keep the existing resolved bundles stable, so it does not force B to rewire its import of foo to the new version.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/usesconstraint/8.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This behaviour can be counter-intuitive. OSGi &lt;strong&gt;never&lt;/strong&gt; dynamically rewires imports when new bundles are installed, it only tries to find wirings for the newly installed bundles. This is because rewiring is expensive: it can force the shutdown and restart of many bundles, and just calculating all the wirings again takes some time (&lt;a href=&quot;http://stackoverflow.com/questions/2085106/is-the-resolution-problem-in-osgi-np-complete&quot;&gt;it is NP-complete&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;We can force OSGi to rewire everything by issuing the &lt;code class=&quot;highlighter-rouge&quot;&gt;refresh&lt;/code&gt; command at the shell. If we do this, B’s wiring will switch to use foo 2.0 from D, and C will resolve. Therefore to check whether you have a problem with installation order:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Just type &lt;code class=&quot;highlighter-rouge&quot;&gt;refresh&lt;/code&gt; and see whether the problem goes away&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;any-more-general-advice&quot;&gt;Any More General Advice?&lt;/h2&gt;

&lt;p&gt;Solving a uses-constraint violation requires us to find an accurate diagnosis first, before we attempt to prescribe a cure.&lt;/p&gt;

&lt;p&gt;Once the diagnosis is confirmed, seek a cure based on configuring the platform rather than messing with bundle manifests: uses-constraint violations are signals of an invalid deployment, i.e. a set of bundles that cannot work together. They are usually not signs of a development problem to be fixed within the bundles themselves – unless the bundles can be shown conclusively to have inaccurate or invalid manifests.&lt;/p&gt;

&lt;p&gt;Regarding diagnosis, a necessary precondition for any uses-constraint violation is multiple exporters of the same package. So the first question to ask ourselves is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are there any obvious sources of multiple exports of the same package?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, have we included two versions of the same bundle? Are there bundles with overlapping exports?&lt;/p&gt;

&lt;p&gt;Using the &lt;code class=&quot;highlighter-rouge&quot;&gt;packages&lt;/code&gt; command in the Equinox shell can help to find multiple exporters, and tells us which bundles are using each export.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If running on Java 6, could one of the new JRE packages be the source of the problem?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s a list of all the packages in Java 6 that were not in Java 5:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;javax.activation                    javax.xml.crypto.dom
javax.annotation                    javax.xml.crypto.dsig
javax.annotation.processing         javax.xml.crypto.dsig.dom
javax.jws                           javax.xml.crypto.dsig.keyinfo
javax.jws.soap                      javax.xml.crypto.dsig.spec
javax.lang.model                    javax.xml.soap
javax.lang.model.element            javax.xml.stream
javax.lang.model.type               javax.xml.stream.events
javax.lang.model.util               javax.xml.stream.util
javax.script                        javax.xml.transform.stax
javax.tools                         javax.xml.ws
javax.xml.bind                      javax.xml.ws.handler
javax.xml.bind.annotation           javax.xml.ws.handler.soap
javax.xml.bind.annotation.adapters  javax.xml.ws.http
javax.xml.bind.attachment           javax.xml.ws.soap
javax.xml.bind.helpers              javax.xml.ws.spi
javax.xml.bind.util                 javax.xml.ws.wsaddressing
javax.xml.crypto                    org.w3c.dom.xpath&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With regard to prescribing a cure, the general approach is to find an alternative bundle or set of bundles that can provide the dependencies we need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does an alternative non-conflicting source for the dependency exist?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If JRE packages are involved, can the additional exporters be removed? Try specifying package versions in the Java profile.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the JRE is not involved and no alternative supply of the dependencies can be found, then maybe these bundles really cannot be used together: they are simply incompatible. This is bad news to be sure, but it’s better to find it out early from the OSGi resolver than from weeks of debugging a misbehaving runtime.&lt;/p&gt;

&lt;h2 id=&quot;does-it-really-have-to-be-this-hard&quot;&gt;Does It Really Have to Be This Hard?&lt;/h2&gt;

&lt;p&gt;I hope not! Clearly this kind of analysis is still based on too much in-depth knowledge of OSGi’s internal workings, which puts it beyond the capabilities of most developers. This could be a real problem for adoption of OSGi in complex enterprise applications.&lt;/p&gt;

&lt;p&gt;As ever, we need better tools. My dream is to create tooling in &lt;a href=&quot;http://bndtools.org&quot;&gt;Bndtools&lt;/a&gt; that will help to quickly diagnose and offer fixes for problems like this. Here I’d like your suggestions… what kind of tooling would help?&lt;/p&gt;

&lt;p&gt;I’m thinking about some kind of graphical tool that can build diagrams on the fly similar to those in this blog post, including the “class space” visualisation. My concern is that it might not scale to a realistic scenario: perhaps the diagrams would just be too big and complex to be any use. I’m just not sure at this point.&lt;/p&gt;

&lt;h2 id=&quot;anything-else-to-say&quot;&gt;Anything Else to Say?&lt;/h2&gt;

&lt;p&gt;Yes: well done for making it all the way through, and happy hunting.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Master OSGi this Summer</title>
     <link href="http://njbartlett.name/2011/08/12/masterclass-sweden.html"/>
     <updated>2011-08-12T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/08/12/masterclass-sweden</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;This is a &lt;strong&gt;final call&lt;/strong&gt; for anybody wishing to seriously &lt;strong&gt;master&lt;/strong&gt; OSGi.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/logomasterclassStockholmSweden201108.png&quot; alt=&quot;&quot; /&gt;:http://www.aqute.biz/MasterClass/20110830&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.aqute.biz/MasterClass/20110830&quot;&gt;Masterclass on OSGi&lt;/a&gt; is approaching at the end of this month. It is a gathering of elite architects and developers from across Europe to learn about how to apply modularity in the real world.&lt;/p&gt;

&lt;p&gt;The plan is to lock ourselves into a hotel on a beautiful but remote Swedish island in the archipelago around Stockholm, and not emerge until we have solved the problems of modularity once and for all! Everything is covered: from top-down architecture to low-level details; through IDEs, build systems, repositories, deployment, distribution and provisioning.&lt;/p&gt;

&lt;p&gt;Okay so we’re not literally going to be locked in, you will be free to explore the area, and you could even bring your partner and children. Make no mistake though, this is far more intense than a normal training course and you will probably be up late each evening bouncing around ideas or coding up prototypes to show off next morning.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/Djuronaset.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Currently we are ten people, including Peter and me. A few words about us: Peter has been working on OSGi since its beginning 12 years ago, and has vast experience in architecting modular systems. He also has encyclopædic knowledge of the specifications and the motivations behind all the design choices. I have been using OSGi “only” since 2003, but have developed several large and complex applications using it. Since I often do training or work with less experienced developers, I am acutely aware of where OSGi’s ease-of-use is lacking, and I have built tools (e.g. &lt;a href=&quot;http://bndtools.org/&quot;&gt;bndtools&lt;/a&gt;) to make OSGi more comprehensible and accessible.&lt;/p&gt;

&lt;p&gt;If this sounds good then you’re going to have to act fast, since the hotel has only a few rooms left. Just click the big banner above, and I look forward to seeing you there.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>How To Embed OSGi</title>
     <link href="http://njbartlett.name/2011/07/03/embedding-osgi.html"/>
     <updated>2011-07-03T09:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/07/03/embedding-osgi</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;A popular question on mailing lists and &lt;a href=&quot;http://stackoverflow.com/questions/4673406/programatically-start-osgi-equinox&quot;&gt;Stack Overflow&lt;/a&gt; is how to embed OSGi in a larger application. This is really easy to do, especially since a standard API for it was introduced in OSGi Release 4.1. Because of the standard, switching between Equinox, Felix and Knopflerfish can be as simple as a configuration change.&lt;/p&gt;

&lt;p&gt;(Tangent: another popular question is “which OSGi framework implementation should I choose?”. The only possible answer is: “it depends”. Each framework has different non-functional characteristics, e.g. with respect to memory consumption, scalability, and so on. By sticking to the standard and remaining agnostic, we can develop our entire application and then test which framework best fits our specific needs).&lt;/p&gt;

&lt;p&gt;Here’s how to do it.&lt;/p&gt;

&lt;h2 id=&quot;create-and-start-the-framework&quot;&gt;Create and Start the Framework&lt;/h2&gt;

&lt;p&gt;The framework launching API uses the Java SPI mechanism to load a “framework factory”. Assuming we have some R4.1-compliant OSGi framework on the classpath, the following will work:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;FrameworkFactory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frameworkFactory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServiceLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
                     &lt;span class=&quot;n&quot;&gt;FrameworkFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;iterator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HashMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// TODO: add some config properties&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Framework&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;framework&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frameworkFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;newFramework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We now have an OSGi framework running, but it’s not very useful until we add some bundles. Let’s do that next.&lt;/p&gt;

&lt;h2 id=&quot;add-bundles&quot;&gt;Add Bundles&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Framework&lt;/code&gt; object that was returned from &lt;code class=&quot;highlighter-rouge&quot;&gt;newFramework&lt;/code&gt; is actually a sub-interface of &lt;code class=&quot;highlighter-rouge&quot;&gt;Bundle&lt;/code&gt;, from which we can get a &lt;code class=&quot;highlighter-rouge&quot;&gt;BundleContext&lt;/code&gt;. If you have ever written a bundle activator then you are familiar with &lt;code class=&quot;highlighter-rouge&quot;&gt;BundleContext&lt;/code&gt; already: it’s the central point of access to the entire OSGi API.&lt;/p&gt;

&lt;p&gt;Let’s install the Felix Shell bundles (NB these bundles work just fine on Equinox and Knopflerfish also):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;BundleContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getBundleContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;installedBundles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LinkedList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;();&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;installedBundles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;installBundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
                     &lt;span class=&quot;s&quot;&gt;&quot;file:org.apache.felix.shell-1.4.2.jar&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;installedBundles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;installBundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
                     &lt;span class=&quot;s&quot;&gt;&quot;file:org.apache.felix.shell.tui-1.4.1.jar&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bundle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;installedBundles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that as a general principle, when we want to install a set of bundles we should install them all &lt;strong&gt;first&lt;/strong&gt; and then start them. If you tried to install and start them individually then you would have to be careful about ordering… much better to let the framework sort it all out!&lt;/p&gt;

&lt;p&gt;Also bear in mind that there is no error handling in the above code. To improve this we should catch any exceptions on install or start, so that we can still install/start the other bundles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; another thing to be careful of is fragment bundles. Fragments cannot be started, so the &lt;code class=&quot;highlighter-rouge&quot;&gt;bundle.start()&lt;/code&gt; line will throw an exception if the installed bundle was a fragment. You may want to add the following check to avoid those exceptions:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getHeaders&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FRAGMENT_HOST&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;n&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;handling-shutdown&quot;&gt;Handling Shutdown&lt;/h2&gt;

&lt;p&gt;Once the framework is running with the bundles you want, you should just let it run until it finishes. Usually the shutdown signal should come from within OSGi, for example the user might type &lt;code class=&quot;highlighter-rouge&quot;&gt;shutdown&lt;/code&gt; at the Felix shell. This would stop the framework, and you would normally want to do something after this has happened.&lt;/p&gt;

&lt;p&gt;For example, if you are writing a straightforward launcher then you probably want to call &lt;code class=&quot;highlighter-rouge&quot;&gt;System.exit()&lt;/code&gt; after OSGi stops. The cleanest way to do this is as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;framework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;waitForStop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;waitForStop&lt;/code&gt; method simply blocks the main thread until OSGi stops, so it is the last thing we do after performing all of our initialisation steps. We can’t just allow the main thread to finish and expect the JVM to shut down, because any of the bundles in the OSGi framework might have started a non-daemon thread, so we need &lt;code class=&quot;highlighter-rouge&quot;&gt;System.exit()&lt;/code&gt; in order to actually shut down.&lt;/p&gt;

&lt;h2 id=&quot;exposing-application-packages&quot;&gt;Exposing Application Packages&lt;/h2&gt;

&lt;p&gt;When embedding OSGi we might want the bundles inside the OSGi framework to have visibility of types from the parent application. The way to do this is to expose those types as exports of the system bundle; then the bundles that wish to see those types can import them with &lt;code class=&quot;highlighter-rouge&quot;&gt;Import-Package&lt;/code&gt; in the usual way.&lt;/p&gt;

&lt;p&gt;For example suppose our parent application contains a domain model in the package &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.mydomain&lt;/code&gt;. This package needs to be added to the system bundle exports, so go back to the first code sample and insert the following where we had the TODO marker:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FRAMEWORK_SYSTEMPACKAGES_EXTRA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
           &lt;span class=&quot;s&quot;&gt;&quot;org.example.mydomain&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The bundle that uses this package should have the following in its manifest:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;Import-Package: org.example.mydomain&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The framework will wire up this import to the export offered by the system bundle. Note that the importing bundle doesn’t care that the package comes from the system bundle, it could just as easily import from an ordinary bundle! This gives us the flexibility to refactor our application. In the future we might want to do more in OSGi, so the domain model packages would be inside an ordinary bundle in OSGi rather than outside it.&lt;/p&gt;

&lt;p&gt;The technique works for any package that is on the classpath of the launcher class. I once had a requirement to embed OSGi in a J2EE application server and expose some EJBs to the OSGi bundles: so &lt;code class=&quot;highlighter-rouge&quot;&gt;javax.ejb&lt;/code&gt; and a few other packages had to go on the system bundle exports. The EJB instances were published into OSGi as services.&lt;/p&gt;

&lt;h2 id=&quot;other-configuration&quot;&gt;Other Configuration&lt;/h2&gt;

&lt;p&gt;There are other configuration changes that can be made in a standard way using the properties you pass to &lt;code class=&quot;highlighter-rouge&quot;&gt;newFramework&lt;/code&gt;. Here are a couple of the more useful ones:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Control where OSGi stores its persistent data:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FRAMEWORK_STORAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;/Users/neil/osgidata&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Request OSGi to clean its storage area on startup&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FRAMEWORK_STORAGE_CLEAN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Provide the Java 1.5 execution environment&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;FRAMEWORK_EXECUTIONENVIRONMENT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;J2SE-1.5&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Of course there are a few framework-specific properties as well, for example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Turn on the Equinox console on port 1234 (Equinox only)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;osgi.console&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;1234&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

</content>
   </entry>
 
   <entry>
     <title>Using EMF in OSGi</title>
     <link href="http://njbartlett.name/2011/07/02/emf-in-osgi.html"/>
     <updated>2011-07-02T14:30:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/07/02/emf-in-osgi</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;It’s official – I ♥ &lt;a href=&quot;http://www.eclipse.org/emf&quot;&gt;EMF&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;This is a surprise to me. I previously regarded modelling in general and EMF specifically as a sort of cult… obscure jargon, terrible documentation, unbearably aloof and patronising &lt;a href=&quot;http://www.eclipsecon.org/2009/sessions?id=358..&quot;&gt;talk abstracts&lt;/a&gt;. but all that’s behind me now. I see the light: it’s all about the industrialisation of software, which requires both &lt;em&gt;componentisation&lt;/em&gt; and &lt;em&gt;automation&lt;/em&gt;. OSGi provides admirably for the first, and perhaps EMF can provide for the second.&lt;/p&gt;

&lt;p&gt;However I wouldn’t say I’m an &lt;em&gt;entirely&lt;/em&gt; orthodox EMFite. I’ve had to hack it about a bit, primarily to get it to work properly OSGi. At first blush using EMF in OSGi may seem trivial, after all, Eclipse is an OSGi application and EMF is designed to work in Eclipse, so EMF must work well in OSGi. Also: all cats have four legs; my dog has four legs; therefore my dog is a cat. Ahem.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/emfosgi/semiskimmed.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;EMF supports running in two distinct environments, neither of which matches my requirements. The first is in a “full-fat” Eclipse SDK or Eclipse RCP application. The second is in a traditional non-OSGi Java runtime, which the EMF docs refer to as “standalone”. However the middle ground – an OSGi environment that is not Eclipse – is not supported. That is, you cannot drop EMF into a lightweight OSGi runtime, even allowing for a few dependencies. It depends on the following eight bundles as an absolute minimum:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;org.eclipse.core.runtime&lt;/li&gt;
  &lt;li&gt;org.eclipse.equinox.common&lt;/li&gt;
  &lt;li&gt;org.eclipse.core.jobs&lt;/li&gt;
  &lt;li&gt;org.eclipse.equinox.registry&lt;/li&gt;
  &lt;li&gt;org.eclipse.equinox.preferences&lt;/li&gt;
  &lt;li&gt;org.eclipse.core.contenttype&lt;/li&gt;
  &lt;li&gt;org.eclipse.equinox.app&lt;/li&gt;
  &lt;li&gt;org.eclipse.osgi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last one is the killer: Equinox itself, meaning that EMF will run only on Equinox, not any other OSGi framework implementation such as Apache Felix or Knopflerfish.&lt;/p&gt;

&lt;p&gt;There’s something fishy going on, though. How can EMF run in a “standalone” non-OSGi environment – with &lt;em&gt;no&lt;/em&gt; other JARs on the classpath – but not run in Felix??&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/emfosgi/deps.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The explanation is that the EMF bundles have poor internal cohesion. In fact only the activators have a hard dependency on Eclipse classes; other parts of EMF reference them only by reflection. Since bundle activators are ignored in non-OSGi runtimes, EMF works fine there without having to put big chunks of Eclipse on the classpath. However it fails in an OSGi environment where the activator is not ignored – actually it fails during resolution, long before the activators are triggered. As far as I can tell the activators do nothing that is useful outside of Eclipse.&lt;/p&gt;

&lt;p&gt;Hopefully the diagram clarifies the problem. We want the green bits but not the red bits; since the green is packaged into the same bundle as part of the red, we have to get all of the red.&lt;/p&gt;

&lt;p&gt;The worst consequence is that if you use EMF to generate code for your model then your model API – even the &lt;em&gt;interfaces&lt;/em&gt;! – will be inextricably linked to EMF and will therefore be encumbered with all those dependencies as well. As &lt;a href=&quot;http://alblue.bandlem.com/2010/11/using-emf-for-osgi-service-creation.html&quot;&gt;Alex discovered&lt;/a&gt;, the links to EMF can be minimised but not completely eliminated, and anyway to remove them would be to throw away some of the most useful functionality of EMF.&lt;/p&gt;

&lt;p&gt;Frankly this is the kind of screw-up that makes me want to strangle Eclipse, if only it didn’t have so many necks. But can it be fixed?&lt;/p&gt;

&lt;p&gt;If backwards compatibility were not a concern then the fix would be very simple: first, refactor the activator out into a separate bundle; then mark the dependencies optional. However, backwards compatibility is &lt;strong&gt;always&lt;/strong&gt; a concern, so the EMF project is &lt;a href=&quot;https://bugs.eclipse.org/bugs/show_bug.cgi?id=328227&quot;&gt;unlikely ever to do this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The alternative is to repackage EMF into new bundles with better OSGi manifests. So that is what I’ve done, and I’m making them available so that others can enjoy the benefits of EMF without hitching themselves to the Eclipse juggernaut. &lt;a href=&quot;http://www.aQute.biz/Code/Bnd&quot;&gt;Bnd&lt;/a&gt; makes it so simple to slice n’ dice the JARs into proper bundles. Everything’s available from my GitHub page at &lt;a href=&quot;http://github.com/njbartlett/emf-osgi&quot;&gt;http://github.com/njbartlett/emf-osgi&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It’s a work in progress; the bundles available so far are as follows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;name.njbartlett.osgi.emf.minimal&lt;/code&gt; contains what appears to be the minimal set of packages required for any EMF-based model. This corresponds to the original &lt;code class=&quot;highlighter-rouge&quot;&gt;org.eclipse.emf.ecore&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;org.eclipse.emf.common&lt;/code&gt; bundles.&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- --&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;name.njbartlett.osgi.emf.xmi&lt;/code&gt; contains classes for XMI marshalling/unmarshalling. It has the same content as the original &lt;code class=&quot;highlighter-rouge&quot;&gt;org.eclipse.emf.ecore.xmi&lt;/code&gt; bundle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As the bundle symbolic names are different, you’re going to be out of luck using them if you use Require-Bundle for your dependencies… but if you do use Require-Bundle then you’re not probably not interested in minimising dependencies and being portable, so you might as well use the original bundles.&lt;/p&gt;

&lt;p&gt;Be sure not to be misled by the name “minimal” – this is still a fairly chunky bundle, weighing in at over 1Mb. That appears to be the minimum cost of using EMF, and certainly in some scenarios it is too much, but then again in many others it is a drop in the ocean. There is no free lunch, after all.&lt;/p&gt;

&lt;p&gt;That’s it for now. I’m only at the start of my EMF journey, and I fully expect to be whacked off course a few more times. Still it seems to be a journey worth taking.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>The JDK8 Module System Requirements</title>
     <link href="http://njbartlett.name/2011/05/27/jdk8-modularity-requirements.html"/>
     <updated>2011-05-27T06:30:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/05/27/jdk8-modularity-requirements</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;blockquote&gt;
  &lt;p&gt;“There’s something very important I forgot to tell you. Don’t cross the streams… It would be bad… Try to imagine all life as you know it stopping instantaneously and every molecule in your body exploding at the speed of light.”
– Egon Spengler (Harold Ramis), &lt;a href=&quot;http://www.imdb.com/title/tt0087332/quotes&quot;&gt;Ghostbusters&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have reviewed the &lt;a href=&quot;http://openjdk.java.net/projects/jigsaw/doc/draft-java-module-system-requirements-12&quot;&gt;JDK8 Module System Requirements&lt;/a&gt; document just published by Mark Reinhold.&lt;/p&gt;

&lt;p&gt;The first thing to note is that this is a &lt;em&gt;much&lt;/em&gt; more positive and constructive document than anything I have seen previously from Mark on this subject. At last the need to interoperate with the existing standard for Java modularity – that is, OSGi – is recognised and specified as a non-negotiable requirement. So that’s excellent news.&lt;/p&gt;

&lt;p&gt;The second point of note is that the requirements for this new module system are really not that far from OSGi itself! Aside from cosmetic differences, such as the location and format of module metadata, the general goals are quite closely aligned and achievable with OSGi. For example, I think that if there were a strong desire to encode metadata in a file named “module-info.java” instead of a file named “MANIFEST.MF” then an agreement could be reached within the auspices of the OSGi Alliance.&lt;/p&gt;

&lt;p&gt;In other areas, the proposed module system – which I’ll call “Jigsaw” for now, though it’s unclear if that will be the proper name going forward – is a more permissive superset of OSGi and would be compatible with it. For example it imposes no semantics on versions except that they must be totally ordered, whereas OSGi additionally specifies how many version segments should be used and what are the semantics of an increment in each segment. OSGi’s semantics provide excellent guidance for developing and evolving software, whereas Jigsaw’s are more adaptable to the version schemes used by existing software (actually most existing software uses insane, arbitrary and inconsistent versioning schemes that are driven more by Marketing than by reality). Nevertheless this represents progress, since previous Jigsaw proposals did not even allow for two versions to be compared with each other.&lt;/p&gt;

&lt;p&gt;So why create a new module system at all? Why not just implement a few small changes in OSGi to support these new requirements? After all, Oracle and IBM working together probably have the clout within the OSGi Alliance to achieve this, whereas Sun working alone did not.&lt;/p&gt;

&lt;p&gt;There is to my mind one big difference that justifies a continued separation. Jigsaw will be used to modularise the Java platform itself, which means it must have features capable of dissecting the tangled mess of packages in the JRE standard library. Even I, a total OSGi bigot, have accepted for some time now that a non-OSGi solution may be necessary for this one specific use-case. That is because, in the Java world, the JRE is unique.&lt;/p&gt;

&lt;p&gt;The JRE is an old API that has evolved organically and with very little planning, and as a result it is a tangled mess that cannot be separated cleanly along package lines. In this regard at least, it is not unique at all, but depressingly normal. However when other APIs get into this state we refactor them… which leads to breakages of downstream libraries and applications, but we can cope if we have a functional version system. Unfortunately refactoring the JRE now would literally &lt;strong&gt;break every Java application and library in the entire world&lt;/strong&gt;. So we need a way to modularise without moving classes between packages. In other words we need to split packages across module boundaries.&lt;/p&gt;

&lt;p&gt;It’s a common misconception that OSGi does not support split packages; it does. There is a form of module dependency called Require-Bundle in which the depending bundle sees an aggregate view of all the packages exported from its dependencies. The thing is, splitting packages is usually such a bad idea that any OSGi egghead will simply tell you: &lt;strong&gt;don’t split the packages&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Don’t split the packages, and &lt;strong&gt;don’t cross the streams&lt;/strong&gt;… except right at the end of the movie, when the Ghostbusters do cross the streams because they’re in the one situation where nothing else will work.&lt;/p&gt;

&lt;p&gt;One reason why split packages are bad is because they break Java accessibility rules. Remember that default accessibility in Java is “package private”: a member or a type that can only be accessed by other types in the same package. The current &lt;a href=&quot;http://java.sun.com/docs/books/jvms/second_edition/html/ConstantPool.doc.html#75929&quot;&gt;JVM specification (section 5.4.4)&lt;/a&gt; says that types or members with default accessibility can be accessed by other members of the same &lt;strong&gt;runtime&lt;/strong&gt; package, where the runtime package is defined as the combination of the package name and the class loader. In OSGi each module has its own class loader, so the runtime package of classes in each module is always different, even if some classes have the same package name. So applying OSGi with Require-Bundle to the JRE would result in IllegalAccessErrors.&lt;/p&gt;

&lt;p&gt;Jigsaw’s solution is to provide a mechanism – the details of which are not yet specified – for certain modules to share a class loader. Remarkably, this is really the only major requirement in the Jigsaw document not already supported by OSGi. It would fix the accessibility problem, and also certain other problems where a class expects to be able to load other classes dynamically through its own class loader.&lt;/p&gt;

&lt;p&gt;However, as necessary as it may be, Jigsaw’s shared-class-loader solution creates more problems than it solves. OSGi’s class loaders serve to create a barrier between modules, allowing private implementation to be hidden. Jigsaw tears down those boundaries, allowing non-modular code to be repackaged into module-like deployment units. This allows it to be applied to the toughest of legacy code, but at the same time it does nothing to discourage the ill-disciplined development practices that got us into this mess.&lt;/p&gt;

&lt;p&gt;It’s like trying to lose weight through liposuction, rather than through diet and exercise.&lt;/p&gt;

&lt;p&gt;Also the access rule problem is far from the only issue arising from split packages. See the OSGi core specification, section 3.12.3, for some more good reasons not to do it. Admittedly none are as bad as making your molecules explode at the speed of light, but they’re pretty bad.&lt;/p&gt;

&lt;p&gt;Of equal concern is tooling: I believe that tooling to develop and manage modules with fine-grained sub-package splitting will be extremely complex and nigh unusable. In OSGi with our focus on coherent packages, it has still taken us a very long time to develop tools that are easy to use for the majority of developers. This is not due to accidental complexity in OSGi, but inherent complexity in developing modular, reusable software. A module system that encourages split packages will require tools that can manage modularity at the level of types rather than packages. How many types are there in an average Java package… twenty, thirty? That is how many &lt;strong&gt;times&lt;/strong&gt; more difficult it will be to design and assemble coherent modules with Jigsaw.&lt;/p&gt;

&lt;p&gt;Sadly when you put a powerful yet dangerous tool in the hands of developers and warn them to never, ever use it except as a last resort, many of them use it as a first resort just to prove what geniuses they are. Lest you think I’m being sanctimonious, I know that I’m guilty of riding this power trip as well, from time to time.&lt;/p&gt;

&lt;p&gt;So while I accept the need for Jigsaw in modularising the Java platform, and am happy for certain Jigsaw requirements to migrate into OSGi, I remain opposed to its use anywhere else. OSGi’s Module Layer provides all the power anybody could reasonably need to build highly modular software, and I have not even talked yet about the OSGi Service Layer, where OSGi’s power really shines – something entirely absent from Jigsaw.&lt;/p&gt;

&lt;p&gt;OSGi has rules, and those rules provide guidance and a framework for creating modular software. Jigsaw’s permissiveness will be seductive because it will allow painful decisions to be deferred indefinitely. Its additional power will cause great damage if applied to the wrong problems in the wrong way. No wonder it is named after a tool notorious for chopping off fingers.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Concurrent Vaadin</title>
     <link href="http://njbartlett.name/2011/05/25/concurrent-vaadin.html"/>
     <updated>2011-05-25T14:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/05/25/concurrent-vaadin</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;As my colleagues and regular readers know, I have been hugely impressed by &lt;a href=&quot;http://www.vaadin.com&quot;&gt;Vaadin&lt;/a&gt;, a web framework for Java, and have been using it in many of my OSGi demos, tutorials and projects.&lt;/p&gt;

&lt;p&gt;This blog post is not about OSGi, but the more general problem of dealing with concurrent updates in a Vaadin application. I describe a technique for updating the application display in response to asychronous events. My own use-case was handling service binding/unbinding events in OSGi, but the technique would equally apply to message processing applications, etc.&lt;/p&gt;

&lt;p&gt;Vaadin’s programming model feels very much like working with a conventional desktop GUI API such as Swing or SWT/JFace, though it is more elegant than either of those examples. However one aspect where it differs significantly is its lack of an “event thread”, which in desktop APIs is responsible for continuously painting the screen and responding to keyboard and mouse clicks.&lt;/p&gt;

&lt;p&gt;Rather, Vaadin controls are backed by a data structure on the server side, which is queried by the HTTP server thread when the browser makes a request – the HTTP server thread is generally owned by the Application Server. Therefore at the first approximation, we merely need to mutate the data structure in response to our async event, and the HTTP request will see the changed value when the next request occurs (this would be when the user clicks a button or refreshes the page… I will ignore “push” technologies for now – i.e., COMET, Web Sockets – since they are not currently supported in core Vaadin).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/vaadin-concurrency.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately the first approximation quickly fails because it is not safe. The HTTP request might arrive while we are in the middle of mutating the data structure, so it will see data in an inconsistent state. Or it might see the old value of the data, even if the request occurs after the update in terms of wall-clock time, because of the way caches work on modern CPUs.&lt;/p&gt;

&lt;p&gt;To ensure that the changes we make to the data are both &lt;em&gt;visible&lt;/em&gt; and &lt;em&gt;consistent&lt;/em&gt; when read by the request thread, we have to perform them in a &lt;code class=&quot;highlighter-rouge&quot;&gt;synchronized&lt;/code&gt; block, and furthermore we must synchronize on the same object that the HTTP request thread synchronizes on. This topic is not well documented in the &lt;a href=&quot;http://vaadin.com/book&quot;&gt;Book Of Vaadin&lt;/a&gt;, but several messages on the forums indicate that the main &lt;em&gt;Application&lt;/em&gt; object is the one to synchronize on. Our life is easiest then if we &lt;strong&gt;are&lt;/strong&gt; the main Application. For example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyApp&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Table&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  
  &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;setMainWindow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Demo App&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setFullSize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// This is our async handler&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Message&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addItem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Making the &lt;code class=&quot;highlighter-rouge&quot;&gt;onMessage&lt;/code&gt; method synchronized is enough, because it locks the Application. Be careful with synchronized methods though… it is usually better to reduce the scope of the lock by doing the minimal UI changes in a synchronized block, rather than locking for the entire method.&lt;/p&gt;

&lt;p&gt;Unfortunately things are not so easy when we are writing a CustomComponent, which we commonly do in order to implement a reusable “chunk” of the overall Application. The problem is, we may start receiving async events before the component has been bound into the Application, so we cannot synchronize on the Application because we don’t have visibility of it yet (that is, &lt;code class=&quot;highlighter-rouge&quot;&gt;getApplication()&lt;/code&gt; will return null). The solution is to synchronize on the application if it is bound, but if it is not yet bound then synchronize on the component itself. There are a number of tricky details to take care of though: what if the application becomes bound &lt;em&gt;while&lt;/em&gt; we are handling the async event? We also need to make the &lt;code class=&quot;highlighter-rouge&quot;&gt;setParent()&lt;/code&gt; method synchronized, since that is the method where we are notified of the application being bound.&lt;/p&gt;

&lt;p&gt;To avoid repeating ourselves, we can encapsulate these details into an abstract base class &lt;code class=&quot;highlighter-rouge&quot;&gt;ConcurrentComponent&lt;/code&gt;, as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ConcurrentComponent&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CustomComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setParent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setParent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;  
  &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getParent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;executeUpdate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runnable&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Application&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;application&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This allows us to implement our own component as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyComponent&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConcurrentComponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Table&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Async handler&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;onMessage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Message&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;executeUpdate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Runnable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Item&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addItem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code should be strongly reminiscent of &lt;code class=&quot;highlighter-rouge&quot;&gt;SwingUtilities.invokeLater()&lt;/code&gt; or SWT’s &lt;code class=&quot;highlighter-rouge&quot;&gt;Display.asyncExec()&lt;/code&gt;, which is intentional. Note how the lock on the Component is used directly to execute the operation if the application is unbound, but that lock is released and an Application lock acquired instead when the application is bound.&lt;/p&gt;

&lt;p&gt;I must admit that I am not entirely happy with the necessity of taking two locks in succession for the common case, and worry that it may have a performance impact. However I can’t see an easy fix that retains correctness; perhaps somebody else will be able to suggest one.&lt;/p&gt;

&lt;p&gt;On the chance that any of the above code proves useful, I hereby place it in the Public Domain – use it however you wish.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Bndtools in the Java Tech Journal</title>
     <link href="http://njbartlett.name/2011/05/19/java-tech-journal-on-osgi.html"/>
     <updated>2011-05-19T03:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/05/19/java-tech-journal-on-osgi</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;&lt;img src=&quot;/images/posts/JTJ-2011-04.jpg&quot; alt=&quot;&quot; /&gt;:http://jaxenter.com/java-tech-journal/JTJ-2011-04&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://jaxenter.com/java-tech-journal/JTJ-2011-04&quot;&gt;Java Tech Journal issue 8&lt;/a&gt; is now available for free download, and is dedicated to OSGi.&lt;/p&gt;

&lt;p&gt;The JTJ is an impressive new publication from the folks at &lt;a href=&quot;http://jaxenter.com/&quot;&gt;JAXenter&lt;/a&gt;, with each issue covering a different technology in depth. The current issue contains excellent articles by some of the leading names in OSGi:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;A Gentle Introduction to OSGi&lt;/em&gt;, by Jerome Moliere from Mentor/J;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;What’s New in Core 4.3?&lt;/em&gt; by BJ Hargrave and Peter Kriens from the OSGi Alliance;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Developing OSGi with Bndtools&lt;/em&gt;, by Marcel Offermans and Alexander Broekhuis from Luminis;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;OSGi A La Carte&lt;/em&gt;, by Valentin Mahrwald and Holly Cummins from IBM Hursley labs;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;OSGi and JPA&lt;/em&gt;, by Dmytro Pishchukhin;&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;The Cure for Complexity&lt;/em&gt;, by Richard Nicholson from Paremus (and President of the OSGi Alliance);&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;The Enterprise OSGi Specification&lt;/em&gt;, by Tim Diekmann from TIBCO and David Bosschaert from JBoss/Red Hat.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From a personal point of view I’m very pleased to see multiple references to &lt;a href=&quot;http://bndtools.org/&quot;&gt;Bndtools&lt;/a&gt; as a tool for developing OSGi bundles, not just in Marcel and Alexander’s article but also in Jerome’s tutorial and in Holly and Valentin’s piece about the tooling ecosystem. Thanks to all the authors for your kind words — your cheques are in the post ;-)&lt;/p&gt;

&lt;p&gt;Stay tuned for some exciting announcements about Bndtools, coming up very soon…&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>OSGi and IKEA</title>
     <link href="http://njbartlett.name/2011/05/11/osgi-ikea.html"/>
     <updated>2011-05-11T11:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/05/11/osgi-ikea</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Mario Fusco wrote a &lt;a href=&quot;https://twitter.com/#!/mariofusco/status/68209314178928640&quot;&gt;thought-provoking tweet&lt;/a&gt; this morning:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ikea / furnishing = OSGi / software : They allow to have very modular things, but trying to put them together generally drives you crazy&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is an interesting analogy, but I obviously take issue with the implied criticism of OSGi. So let’s break it down.&lt;/p&gt;

&lt;p&gt;The first thing to say is that I actually find IKEA furniture quite easy to build, and I doubt I am alone in this. Especially once you have built a few, you find there are common patterns… similar tools, similar kinds of connectors and so on. The instructions are so simple that they don’t even need any text, and in many cases you can still complete the build even if you’ve lost the intructions.&lt;/p&gt;

&lt;p&gt;The main sources of frustration are errors: missing parts, or poorly machined connectors that don’t fit they way they should. Fortunately these problems are rare – when a part IS missing, it’s nearly always because I have lost it myself.&lt;/p&gt;

&lt;p&gt;Is there an alternative to this kind of modular construction? Of course. The previous generation of manufactured furniture consisted of completely whole, inflexible objects, produced in huge quantities. A desk, for example, was available in specific dimensions and with a specific number of drawers. If that desk didn’t fit the corner where you wanted to put it, then you had two choices: hope somebody else &lt;em&gt;did&lt;/em&gt; sell a desk of the right size… or move house.&lt;/p&gt;

&lt;p&gt;Before mass production, furniture was assembled by craftsmen. It was gorgeous, high quality, fit precisely to your requirements… and cost literally thousands of times more than an equivalent IKEA product.&lt;/p&gt;

&lt;p&gt;Today most software is produced according to one of these two models. They are packaged COTS software and bespoke in-house applications, respectively. There is nothing wrong with either approach: if your requirements are conventional then a COTS solution is best; if your requirements are unique (and you have deep pockets) then building bespoke is the way to go. But there is a huge gulf between these models, and if your requirements fall somewhere between the two then you face either making do with software that isn’t quite what you need, or spending a fortune building your own thing from scratch.&lt;/p&gt;

&lt;p&gt;There has to be a better way… an IKEA way… and that’s exactly what OSGi is. It empowers the end customer to assemble modules into a finished article that meets their needs, going way beyond the limited customisation abilities of COTS products. At the same time it offers a cost model closer to that of mass production.&lt;/p&gt;

&lt;p&gt;Can OSGi modules drive you crazy when you try to put them together? Yes that happens, and for the same reasons: something is missing, or something is bad quality. IKEA has excellent quality controls over the parts that it sells… third party software authors, well, not so much.&lt;/p&gt;

&lt;p&gt;[Incidentally where does open source fit into this analogy? In my opionion, open source libraries are usually neither comprehensive nor robust enough to correspond to a “component” or “module” in the IKEA sense. I believe they are more like the raw materials: the laminated MDF boards, the screws and connectors and clippy things. These are vital productivity enhancers for the craftsmen who design the components, but they are not components themselves that can be assembled and deployed by end users.]&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Apache Felix Diagnostics for "Uses" Conflicts</title>
     <link href="http://njbartlett.name/2011/03/31/uses-constraints-in-felix.html"/>
     <updated>2011-03-31T09:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/03/31/uses-constraints-in-felix</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Last month I wrote a &lt;a href=&quot;/2011/02/09/uses-constraints.html&quot;&gt;blog post explaining&lt;/a&gt; how “uses constraint” violations come about in OSGi, and gave some heuristic shortcuts for solving them.&lt;/p&gt;

&lt;p&gt;Sometimes though, the shortcuts just don’t work. In the worst case, you have to trace through all of the package dependencies manually in order to find the culprit. Usually the culprit is a duplicated package somewhere in the system, but finding it can be a headache.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Or, so I thought…&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yesterday I ran into just such a problem with a client’s application. Equinox was printing the following error (package names have been changed to protect the innocent):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;!MESSAGE Bundle org.example.foo.xydata [17] was not resolved.
!MESSAGE Package uses conflict: Import-Package:
org.example.foo.util.service&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;None of the shortcuts I talked about in my last post worked, so I began the laborious process of tracing all the package dependencies. I did this for about 30 minutes before remembering that the latest versions of &lt;a href=&quot;http://felix.apache.org/site/index.html&quot;&gt;Apache Felix&lt;/a&gt; have some great new diagnostics for uses constraint violations. After a little work to switch the framework used by the launcher, I managed to get Felix running and was immediately rewarded with the following message:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;Unable to resolve module org.example.foo.xydata [17] because it
is exposed to package 'org.example.foo.util.verify' from
'org.example.foo.framework' and 'org.example.foo.platform.util'
via two dependency chains.

Chain 1:
  org.example.foo.xydata [17]
    import: (package=org.example.foo.util.verify)
     |
    export: package=org.example.foo.util.verify
  org.example.foo.framework [12]

Chain 2:
  org.example.foo.xydata [17]
    import: (package=org.example.foo.bar.datastore)
     |
    export: package=org.example.foo.bar.datastore;
                    uses:=org.example.foo.util.verify
  org.example.foo.bar.datastore [13]
    import: (package=org.example.foo.util.verify)
     |
    export: package=org.example.foo.util.verify
  org.example.foo.platform.util [8]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This gets pretty close – as close as one could get in pure text, I believe – to a graphical representation, which I have attempted to reproduce as follows (omitting the common prefix):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/usesconstraint/9.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Bundle 17 cannot resolve because of the two dashed lines. These two wires cannot both exist at the same time, because that would lead to an inconsistent view of the &lt;code class=&quot;highlighter-rouge&quot;&gt;util.verify&lt;/code&gt; package.&lt;/p&gt;

&lt;p&gt;There is some information missing from Felix’s message and my diagram… why has OSGi chosen to try to wire bundle 17’s import of &lt;code class=&quot;highlighter-rouge&quot;&gt;util.verify&lt;/code&gt; to bundle 12? Just looking at the diagram, it seems like all would be well if it were wired to bundle 8. But of course the diagram is only a piece of the puzzle, and there are other constraints present that prevent the desired wiring (specifically, another import exists that must be resolved from bundle 12 and also uses &lt;code class=&quot;highlighter-rouge&quot;&gt;util.verify&lt;/code&gt;). Nevertheless, there is enough information here to immediately diagnose the real problem: &lt;code class=&quot;highlighter-rouge&quot;&gt;util.verify&lt;/code&gt; has been incorrectly duplicated in multiple bundles. Removing the duplication fixed the problem.&lt;/p&gt;

&lt;p&gt;Granted, the analysis still requires somebody with some high level understanding of OSGi to work out what the underlying problem is. But at least Felix gives a substantial amount of information to work with, rather than leaving us in the dark.&lt;/p&gt;

&lt;p&gt;My client was so impressed that they are considering switching their development to Felix. But even if you remain a committed Equinox user, consider the possibility of using Felix temporarily to obtain diagnostics when you run into such problems. Another reason to use a &lt;a href=&quot;/2011/03/07/embedding-osgi.html&quot;&gt;standard, framework-agnostic launcher&lt;/a&gt; architecture.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Towards Maven Support in Bndtools</title>
     <link href="http://njbartlett.name/2011/03/02/towards-maven-support-in-bndtools.html"/>
     <updated>2011-03-02T14:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2011/03/02/towards-maven-support-in-bndtools</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;A commonly requested enhancement for Bndtools is to enable integration with Maven. Although I don’t tend to use Maven myself, I do recognise that it’s a very popular build tool, especially in big companies with lots of developers.&lt;/p&gt;

&lt;p&gt;That’s why I’ve been working on Maven support for Bndtools, which is now available to try out as an “Alpha” quality pre-release. While not yet particularly stable, I need to get some feedback from real Maven users to guide the rest of the implementation.&lt;/p&gt;

&lt;p&gt;Before going into the details, first a word of reassurance to the non-Maven-users: you absolutely will &lt;strong&gt;not&lt;/strong&gt; have to adopt Maven in order to use Bndtools, and I will &lt;strong&gt;never&lt;/strong&gt; make it a requirement. Bndtools projects can still be built with &lt;a href=&quot;http://www.aQute.biz/Code/Bnd&quot;&gt;Bnd&lt;/a&gt;, which is a very capable tool: for example, the OSGi Alliance uses Bnd to build over 1300 bundles every night.&lt;/p&gt;

&lt;p&gt;On the other hand if you are a committed Maven user already, then Bndtools’ support will make it possible for you to take advantage of powerful OSGi-specific development features in your IDE, without changing your build processes.&lt;/p&gt;

&lt;p&gt;It’s easiest to explain what I have done in a Q&amp;amp;A style. Please add your own questions in the comments.&lt;/p&gt;

&lt;h2 id=&quot;how-does-it-work&quot;&gt;How Does it Work?&lt;/h2&gt;

&lt;p&gt;An important design goal is to avoid duplicating any configuration data. Dependencies and bundle contents/configuration are each defined in exactly &lt;em&gt;one&lt;/em&gt; place only.&lt;/p&gt;

&lt;p&gt;Bndtools should be installed alongside M2Eclipse in the same Eclipse instance. There is a clear division of responsibilities between the two tools:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Maven and M2Eclipse are responsible for build-time dependencies and performing the canonical “offline” build. This in turn uses the &lt;a href=&quot;http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html&quot;&gt;Maven Bundle Plugin&lt;/a&gt;, which is the most popular way to build OSGi bundles with Maven; for example, Apache Felix and all its subprojects are built this way. The Bundle Plugin uses Bnd internally, just like Bndtools.&lt;/li&gt;
  &lt;li&gt;Bndtools is responsible for “on-the-fly” developer builds, launching OSGi frameworks and test runs, and configuring bundle contents.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;why-should-i-use-this&quot;&gt;Why Should I Use This?&lt;/h2&gt;

&lt;p&gt;If you are a current Maven user, then the approach outlined here allows you to easily adapt your existing Maven builds to develop OSGi bundles, using the most popular approach for building bundles with Maven. It does not require major changes to your project structure.&lt;/p&gt;

&lt;p&gt;At the same time you will gain the OSGi specific ease-of-use features of Bndtools (see next question) while still allowing users of other Java IDEs such as NetBeans to easily work on your project.&lt;/p&gt;

&lt;h2 id=&quot;what-does-bndtools-offer-over-m2eclipse&quot;&gt;What Does Bndtools Offer Over M2Eclipse?&lt;/h2&gt;

&lt;p&gt;M2Eclipse is a fully-featured development environment for working with any kind of Maven-built project. However it offers few ease-of-use features for working with &lt;em&gt;specific&lt;/em&gt; project types.&lt;/p&gt;

&lt;p&gt;Bndtools offers a rich and easy-to-use environment specifically for developing OSGi bundles. You can take advantage of the following features:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;On-the-fly generation of the OSGi bundle, and deployment to a running OSGi container, immediately upon saving the source of a Java file.&lt;/li&gt;
  &lt;li&gt;Powerful tools to visualise and manipulate the package-level dependencies of bundles.&lt;/li&gt;
  &lt;li&gt;Tools to configure, run and test an OSGi application, which also work in exactly the same way from the command line.&lt;/li&gt;
  &lt;li&gt;… and more!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, when using the raw Bundle Plugin, the contents of a bundle are controlled via a rather arcane set of instructions embedded in the POM, such as the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;instructions&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;_versionpolicy&amp;gt;&lt;/span&gt;
        [$(version;==;$(@)),$(version;+;$(@)))
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/_versionpolicy&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Export-Package&amp;gt;&lt;/span&gt;
        org.apache.felix.fileinstall;version=${project.version}
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Export-Package&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Import-Package&amp;gt;&lt;/span&gt;
        org.osgi.service.log;resolution:=optional,
        org.osgi.service.cm;resolution:=optional,
        *
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Import-Package&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Private-Package&amp;gt;&lt;/span&gt;
        org.apache.felix.fileinstall.internal,
        org.apache.felix.utils.properties,
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Private-Package&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;Bundle-Activator&amp;gt;&lt;/span&gt;
        org.apache.felix.fileinstall.internal.FileInstall
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/Bundle-Activator&amp;gt;&lt;/span&gt;
    ...&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In contrast Bndtools gives us the following editor (click for full size). Note the Calculated Imports list in the top right, which is recalculated on the fly as we adjust the bundle contents and customise imports; with Maven Bundle Plugin we must do a full build to obtain this information.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/bndtools-editor-small.png&quot; alt=&quot;Bndtools Bundle Editor&quot; title=&quot;Bndtools Bundle Editor&quot; /&gt;:/images/bndtools-editor.png&lt;/p&gt;

&lt;h2 id=&quot;do-i-have-to-use-m2eclipse&quot;&gt;Do I Have to Use M2Eclipse?&lt;/h2&gt;

&lt;p&gt;Yes, for now: to enable Maven support in Bndtools, M2Eclipse is required.&lt;/p&gt;

&lt;p&gt;M2Eclipse provides the build-time classpath that allows Eclipse to compile the Java sources, before Bnd takes over to build the OSGi bundles.&lt;/p&gt;

&lt;p&gt;I am investigating the possibility of directly processing the POM and local repository from within Bndtools. This could provide a lightweight alternative for users that do not need the full suite of functionality offered by M2Eclipse. However, this feature is not yet available.&lt;/p&gt;

&lt;h2 id=&quot;why-not-use-tycho&quot;&gt;Why Not Use Tycho?&lt;/h2&gt;

&lt;p&gt;There is nothing wrong with Tycho, but it is a tool for a different job: it is intended for building projects that have been developed using the Eclipse Plug-in Development Environment (PDE). Projects developed in PDE are very inflexible and require specialised build tools – as a result they have never worked properly with “vanilla” Maven. Tycho works by adapting Maven to the PDE project structure.&lt;/p&gt;

&lt;p&gt;In contrast, Bndtools is more flexible and adapts to your existing build system, whether it is vanilla Maven or something else. To summarise the advantages of using Bndtools with Maven versus Tycho:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Bndtools uses the standard Maven project structure; Tycho uses the PDE project structure.&lt;/li&gt;
  &lt;li&gt;Tycho projects are Eclipse PDE projects, which are difficult (though not impossible) to work on using IDEs other than Eclipse. Bndtools/M2Eclipse projects can be easily worked on by developers using other IDEs, though of course they will miss the ease-of-use features offered by Bndtools.&lt;/li&gt;
  &lt;li&gt;Tycho requires Maven 3, whereas Bndtools works with both Maven 2 and 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These points are distinct from the advantages of Bndtools versus Eclipse PDE, which is a subject for another blog post.&lt;/p&gt;

&lt;p&gt;To be clear: if you are currently using Eclipse PDE to develop your OSGi bundles then you should &lt;em&gt;definitely&lt;/em&gt; use Tycho to build them! On the other hand if you are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a Maven user interested in trying OSGi, or;&lt;/li&gt;
  &lt;li&gt;looking to “OSGify&quot; (or “bundleize&quot;) an existing Maven build, or;&lt;/li&gt;
  &lt;li&gt;already using the Bundle Plugin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…then I believe Bndtools is more likely to fit your needs.&lt;/p&gt;

&lt;h2 id=&quot;how-are-dependencies-specified&quot;&gt;How are Dependencies Specified?&lt;/h2&gt;

&lt;p&gt;In Bndtools/Maven projects the build dependencies are specified entirely in the POM. I.e., the POM is the &lt;em&gt;sole source&lt;/em&gt; of build-time dependencies, and Bndtools uses the build classpath as defined by M2Eclipse to perform its on-the-fly builds.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;-buildpath&lt;/code&gt; feature of Bnd, which is ordinarily specified in &lt;code class=&quot;highlighter-rouge&quot;&gt;bnd.bnd&lt;/code&gt;, should not used when building with Maven.&lt;/p&gt;

&lt;h2 id=&quot;how-are-bundle-contents-specified&quot;&gt;How Are Bundle Contents Specified?&lt;/h2&gt;

&lt;p&gt;The instructions required by Bnd to specify bundle contents and calculate imports are given in the &lt;code class=&quot;highlighter-rouge&quot;&gt;bnd.bnd&lt;/code&gt; file, just as in any other Bndtools project. These instructions are referenced from the POM using the following instruction to the Bundle Plugin:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;instructions&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;_include&amp;gt;&lt;/span&gt;bnd.bnd&lt;span class=&quot;nt&quot;&gt;&amp;lt;/_include&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/instructions&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This means that &lt;code class=&quot;highlighter-rouge&quot;&gt;bnd.bnd&lt;/code&gt; is the &lt;em&gt;sole source&lt;/em&gt; of bundle content and configuration instructions.&lt;/p&gt;

&lt;p&gt;Note that some parameters in the output bundle can be inherited from the POM. For example, we typically want to use the Artifact ID as the symbolic name of the bundle and the POM version as the bundle version. This can be achieved by referencing these properties from &lt;code class=&quot;highlighter-rouge&quot;&gt;bnd.bnd&lt;/code&gt; as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;-include: pom.xml

Bundle-SymbolicName: ${pom.artifactId}
Bundle-Version: ${pom.version}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;can-i-build-multi-bundle-projects&quot;&gt;Can I Build Multi-Bundle Projects?&lt;/h2&gt;

&lt;p&gt;Bnd supports a feature called “sub-bundles”, in which multiple bundles are built from a single project.&lt;/p&gt;

&lt;p&gt;While this feature does still work with a Maven-based build, it is &lt;em&gt;not recommended&lt;/em&gt; because it works against the Maven philosophy of one output artifact per project. Downstream tools and Maven plugins, such as those that assemble the output bundles into a packaging artifact, are unlikely to work correctly with multi-bundle projects.&lt;/p&gt;

&lt;h2 id=&quot;how-do-on-the-fly-builds-work&quot;&gt;How Do On-the-Fly Builds Work?&lt;/h2&gt;

&lt;p&gt;Bnd uses the project classpath – as created by M2Eclipse from the POM – to perform on-the-fly builds of bundles. As ever when using Bndtools, your bundles are always built, and if you are running an OSGi framework from Bndtools they will be immediately deployed into it.&lt;/p&gt;

&lt;p&gt;Since both Bndtools and the Maven Bundle Plugin use Bnd internally, the on-the-fly bundles are exactly the same as those built by Maven in a full offline build.&lt;/p&gt;

&lt;h2 id=&quot;what-is-the-bnd-osgi-repository-used-for&quot;&gt;What Is The Bnd OSGi Repository Used For?&lt;/h2&gt;

&lt;p&gt;When using Bndtools without Maven, Bnd Repository is used to supply bundles for both building and running. However when using Maven, Bndtools is no longer responsible for build dependencies but the Bnd Repository is still used to supply bundles for running and testing OSGi applications.&lt;/p&gt;

&lt;p&gt;This is important because the Maven repositories contain a mixture of different artifact types, and most of the JARs it contains are not OSGi bundles. The Bnd Repository contains exclusively OSGi bundles and so is very useful for actually &lt;em&gt;running&lt;/em&gt; OSGi applications.&lt;/p&gt;

&lt;p&gt;Having said that, a subset of JARs in the Maven repositories are OSGi bundles, and work is in progress to build a Bnd Repository that wraps the Maven local repository to offer those bundles for use at runtime.&lt;/p&gt;

&lt;h2 id=&quot;how-do-i-use-it&quot;&gt;How Do I Use It?&lt;/h2&gt;

&lt;p&gt;First ensure that both M2Eclipse and Bndtools Alpha are installed in your Eclipse IDE. Here is the update site for Bndtools Alpha:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;http://bndtools-alpha-updates.s3.amazonaws.com/&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The next step depends on whether you are creating a new project, or adapting an existing one.&lt;/p&gt;

&lt;h3 id=&quot;creating-a-new-mavenbndtools-project&quot;&gt;Creating a New Maven/Bndtools Project&lt;/h3&gt;

&lt;p&gt;To create a new Maven project with Bndtools support, use &lt;a href=&quot;http://njbartlett.name.s3.amazonaws.com/bndtools-component-archetype-0.0.2-SNAPSHOT.jar&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;bndtools-component-archetype&lt;/code&gt;&lt;/a&gt;. This archetype corresponds to Bndtools’ “Component Template”, and creates a project with support for Declarative Services annotations. The OSGi Core and Compendium APIs are added as dependencies, in addition to JUnit.&lt;/p&gt;

&lt;p&gt;As soon as the Bndtools Maven support is stable, this archetype will be submitted to Maven Central so that it can be directly accessed by Maven/M2Eclipse. For now, you need to click the link to download it, then install into your local repository as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;mvn install:install-file \
    -DgroupId=org.bndtools.archetypes \
    -DartifactId=bndtools-component-archetype \
    -Dversion=0.0.2-SNAPSHOT \
    -Dpackaging=jar \
    -Dfile=./bndtools-component-archetype-0.0.2-SNAPSHOT.jar \
    -DgeneratePom=true&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can now create a new project from the archetype as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;mvn archetype:create \
    -DarchetypeGroupId=org.bndtools.archetypes \
    -DarchetypeArtifactId=bndtools-component-archetype \
    -DarchetypeVersion=0.0.2-SNAPSHOT \
    -DgroupId=org.example \
    -DartifactId=comp1 \
    -Dversion=0.0.1-SNAPSHOT&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then you can import the project into Eclipse using &lt;strong&gt;File&lt;/strong&gt; &amp;gt; &lt;strong&gt;Import&lt;/strong&gt; &amp;gt; &lt;strong&gt;Existing Projects into Workspace&lt;/strong&gt;. You can also use M2Eclipse to create a project from the archetype without leaving Eclipse, but due to an apparent bug in M2Eclipse this throws an error (&lt;code class=&quot;highlighter-rouge&quot;&gt;NullPointerException&lt;/code&gt;). In fact the project is still created, so the error can be safely ignored.&lt;/p&gt;

&lt;h3 id=&quot;adapting-an-existing-maven-project&quot;&gt;Adapting an Existing Maven Project&lt;/h3&gt;

&lt;p&gt;If you have an existing “vanilla” Java Maven project, you can adapt it for use with Bndtools by right-clicking on the &lt;code class=&quot;highlighter-rouge&quot;&gt;pom.xml&lt;/code&gt; and selecting &lt;strong&gt;Add OSGi/Bnd Support&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/bndtools-maven1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This starts a refactoring wizard that performs the following changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Creates a &lt;code class=&quot;highlighter-rouge&quot;&gt;bnd.bnd&lt;/code&gt; file and adds the Bnd “nature” to the Eclipse project;&lt;/li&gt;
  &lt;li&gt;Adds the Maven Bundle Plugin to the build plugins section of the POM, if not already present;&lt;/li&gt;
  &lt;li&gt;Changes the Maven packaging type to “bundle” (required by the Bundle Plugin).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that the changes to the POM will be previewed in the wizard, so you can make sure you are happy with them before clicking Finish.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/bndtools-maven2-small.png&quot; alt=&quot;&quot; /&gt;:/images/bndtools-maven2.png&lt;/p&gt;

&lt;h2 id=&quot;is-that-it&quot;&gt;Is That It?&lt;/h2&gt;

&lt;p&gt;Yes, for now.&lt;/p&gt;

&lt;p&gt;Please give it a try, but don’t expect everything to work. If something that seems like it should work doesn’t, then &lt;a href=&quot;mailto:njbartlett@gmail.com&quot;&gt;drop me a line&lt;/a&gt;. If you think my whole approach is wrong, then tell me how I should be doing this. My goal is to make Bndtools &lt;strong&gt;the easiest&lt;/strong&gt; and fastest way to develop OSGi applications – irrespective of how they are built.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>The JCP... Weep for the Experts</title>
     <link href="http://njbartlett.name/2010/12/09/jcp-weep-for-the-experts.html"/>
     <updated>2010-12-09T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/12/09/jcp-weep-for-the-experts</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Recently I have preferred to stay away from political blog posts, but the occasion of &lt;a href=&quot;https://blogs.apache.org/foundation/entry/the_asf_resigns_from_the&quot;&gt;Apache’s departure from the Java Community Process&lt;/a&gt; (JCP) seems a fitting time to fulminate, just this once.&lt;/p&gt;

&lt;p&gt;As Bill Joy once said:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Most smart people don’t work here… for any definition of ‘here’.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A deep understanding of that principle, and of the value of diversity, led Sun to create the JCP. Java became strong not as a barbershop quartet singing in perfect harmony, but as a massive, heaving soccer crowd baying for their team. The neutering of the JCP threatens to turn that crowd into a bunch of North Korean rent-a-fans.&lt;/p&gt;

&lt;p&gt;There will inevitably be a loss of diversity of brain-power feeding into the Java specification. Java has never been the product of just one company: Sun made a major contribution, yes, but so did IBM, BEA, Ericsson and countless others. They contributed their time, effort and in many cases intellectual property to improving Java because the JCP offered a legal framework for their work to be distributed as an open platform, which benefited everybody.&lt;/p&gt;

&lt;p&gt;That framework was called the Java Specification Participation Agreement (JSPA), and it meant that intellectual property from the Experts on an Expert Group flowed via the Spec Lead and into the final specification, so that independent implementations could be built without fear of copyright or patent claims – so long as they passed the TCK. Stephen Colebourne has a nice pictorial guide to this process in &lt;a href=&quot;http://www.jroller.com/scolebourne/entry/sun_apache_ip_in_pictures&quot;&gt;one of his blog posts.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was the JSPA that Sun and later Oracle broke by refusing to allow Apache to test Harmony with the TCK without “Field of Use” restrictions. The refusal was all the more egregious because it was not entirely their property to withold.&lt;/p&gt;

&lt;p&gt;So what motivation would an expert now have to serve on a JSR Expert Group?&lt;/p&gt;

&lt;p&gt;Take for example Bob “Crazy Bob” Lee, author of Guice, major contributor to the Google Collections API and spec lead of JSR 330, the fastest ever JSR. He was invited to join the expert groups of both the Java 7 and Java 8 JSRs. He is undoubtedly an expert and would have made an excellent contribution to those JSRs… but he &lt;a href=&quot;http://blog.crazybob.org/2010/11/java-se-7-8.html&quot;&gt;declined to participate&lt;/a&gt;. After all, why on Earth should Bob spend his valuable time working on a JSR when the fruits of his labour would be taken by Oracle?&lt;/p&gt;

&lt;p&gt;Doug Lea, who probably knows more about concurrency than anybody on the planet, &lt;a href=&quot;http://gee.cs.oswego.edu/dl/html/jcp22oct10.html&quot;&gt;resigned from the JCP in disgust&lt;/a&gt; for similar reasons. Oddly he continues to work on the OpenJDK, but this is because he is a researcher and it is still possible for him to perform novel research in a closed platform, and Java &lt;strong&gt;is&lt;/strong&gt; still the most advanced managed runtime environment. Wouldn’t he jump ship though if a similarly advanced but more open platform were to emerge? Admittedly I’m speculating about that because I don’t know Doug at all.&lt;/p&gt;

&lt;p&gt;Other resignations include &lt;a href=&quot;http://tembrel.blogspot.com/2010/12/resigned-from-ec.html&quot;&gt;Tim Peierls&lt;/a&gt; and of course Apache. Google will probably follow shortly. They have all realised that they were giving their work and IP to improve a proprietary Oracle product… for nothing.&lt;/p&gt;

&lt;p&gt;The primary remaining motivator is &lt;strong&gt;money&lt;/strong&gt;. Experts will be drawn from the set of people paid by Oracle, directly or indirectly. Oracle employees, obviously. IBM employees too, since it’s clear that Oracle wrote IBM a fat cheque to get them to abandon Harmony and join OpenJDK… the details of the deal are private but I &lt;em&gt;sincerely&lt;/em&gt; hope they emerge on WikiLeaks some day.&lt;/p&gt;

&lt;p&gt;The result will be a dreadful monoculture. Many smart people work at Oracle and IBM, but even more don’t. End users will not have their say, except through official Oracle or IBM sales channels, hence the joke that JCP now stands for “Just Customers Please”. Vendors of small, alternative frameworks will either not contribute or their contributions will be appropriated and assimilated.&lt;/p&gt;

&lt;p&gt;Meanwhile, less pessimistic souls are congratulating Oracle for finally getting Java moving again. Well, &lt;em&gt;Il Duce&lt;/em&gt; made the trains run on time. Enough said.&lt;/p&gt;

&lt;p&gt;Sigh. What’s a poor Java developer to do? I’m not certainly giving up the platform just yet because there still aren’t any better games in town. All the same, it seems wiser than ever to transfer &lt;strong&gt;at least&lt;/strong&gt; a few eggs to alternative baskets. Just in case.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>OSGi Masterclass is Coming to America</title>
     <link href="http://njbartlett.name/2010/11/02/masterclass-usa.html"/>
     <updated>2010-11-02T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/11/02/masterclass-usa</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;&lt;img src=&quot;/images/posts/logo-masterclass-201101.png&quot; alt=&quot;&quot; /&gt;:http://www.aqute.biz/MasterClass/201101-02&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.aqute.biz/MasterClass/201101-02&quot;&gt;Masterclass on OSGi&lt;/a&gt; is coming to the USA!&lt;/p&gt;

&lt;p&gt;After a successful first go in our back yard – i.e., Europe – Peter Kriens and I have fixed a date and location for the USA Edition: 18th to 21st January 2011 in Pleasanton California.&lt;/p&gt;

&lt;p&gt;I’ve never been to Pleasanton but it sounds… well, pleasant. And it’s convenient too, being accessible by BART from San Francisco city and airport. But then again it’s not &lt;strong&gt;too&lt;/strong&gt; close to all those distracting highlights of the big city, and this is something we learned from the first class: a little bit of isolation helps to create a “pressure cooker” in which the ideas bounce around at high speed. It’s exhausting, but definitely extracts a lot of value for the attendees.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/masterclass01/2_web.jpeg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As for the format of the class, it is very different from your usual structured training. The masterclass is about achieving mastery of OSGi, and that cannot be done with a fixed slide deck. Instead we will look at the subjects that interest you, and work out how to apply OSGi to the challenges you see in your environment. Peter and I won’t always have all the answers, but we usually know the right questions and have the experience to reach towards a solution together. But we also expect to have our own opinions and assumptions challenged.&lt;/p&gt;

&lt;p&gt;Needless to say though, we believe that our knowledge of OSGi is second to none. And I don’t mean to imply that we don’t have any slides, or that we have not prepared anything. I have a vast slide deck from my normal training courses, but this will serve as back-up material rather than driving the class.&lt;/p&gt;

&lt;p&gt;The price for the 4-day class is a very reasonable $2200, or $2000 if you register before 1st December. Also if you are attending ApacheCon in Atlanta this week, we have a special discount code for you which will be advertised at the Felix/OSGi meet-up on Thursday evening, and the OSGi Track on Friday.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.regonline.com/Register/Checkin.aspx?EventID=909496&quot;&gt;REGISTER HERE&lt;/a&gt;.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Eclipse on SoyLatte without X11</title>
     <link href="http://njbartlett.name/2010/10/24/eclipse-soylatte-no-x11.html"/>
     <updated>2010-10-24T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/10/24/eclipse-soylatte-no-x11</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;An &lt;a href=&quot;http://www.theregister.co.uk/2010/10/21/apple_threatens_to_kill_java_on_the_mac/&quot;&gt;article by Cade Metz&lt;/a&gt; in The Register suggests that Apple’s deprecation of Java is an attack on Android developers:&lt;/p&gt;

&lt;blockquote&gt;
&quot;If you don't have Java on the Mac, you can't run Java development tools such as Eclipse, IntelliJ, and NetBeans. And though there is a port of OpenJDK for the Mac, it's not quite complete. It's limited to the X11 windows system, and there's no support for native Mac GUIs.

...

&quot;The other salient point here is that if you don't have Java on the Mac, you can't use Google's Android SDK. Most Android development is done on Eclipse, and though Eclipse isn't required by the SDK, the Java environment is.&quot;

&lt;/blockquote&gt;
&lt;p&gt;Don’t believe everything you read in El Reg, folks. &lt;strong&gt;Eclipse runs just fine&lt;/strong&gt; on that &lt;a href=&quot;http://landonf.bikemonkey.org/static/soylatte/&quot;&gt;OpenJDK port (a.k.a. SoyLatte)&lt;/a&gt; &lt;strong&gt;without X11&lt;/strong&gt;. Here’s a screenshot:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/eclipse-soylatte.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;No, I can’t tell a difference from normal Eclipse either, at least visually. It does feel a bit sluggish, so I assume that SoyLatte is not heavily optimised. But that’s a fixable problem.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.eclipse.org/swt/&quot;&gt;SWT&lt;/a&gt; is the key. All the UI customisation work that Apple has put into its JVM was required to support Swing/AWT, which Eclipse does not use. Therefore Eclipse – and Google’s Android tools – will work fine, even if Apple eradicates its JVM from future Mac OS releases and refuses to give its UI code to OpenJDK. The same goes for Eclipse RCP applications such as &lt;a href=&quot;http://www.vuze.com/&quot;&gt;Vuze&lt;/a&gt; and &lt;a href=&quot;http://www.rssowl.org/&quot;&gt;RSSOwl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Sadly the same may not be true of NetBeans and IntelliJ, since they build on a GUI technology that is both tightly coupled to the JVM and requires extensive customisation by the operating system vendor. I wouldn’t miss those other IDEs myself, but it’s good to have choice in the market, so I hope the situation improves for them soon.&lt;/p&gt;

&lt;p&gt;One more screenshot, here is the Eclipse 4.0 early access release:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/e4-soylatte.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; David asked in the comments &lt;strong&gt;how&lt;/strong&gt; to actually run Eclipse on SoyLatte. It’s quite simple. You need to open up the Eclipse.app launcher and edit the file &lt;code class=&quot;highlighter-rouge&quot;&gt;Contents/MacOS/eclipse.ini&lt;/code&gt;. Assuming you have SoyLatte installed at &lt;code class=&quot;highlighter-rouge&quot;&gt;/usr/local/soylatte16-amd64&lt;/code&gt;, insert the following two lines:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;-vm
/usr/local/soylatte16-amd64/bin/java&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;These two lines must go &lt;strong&gt;above&lt;/strong&gt; the &lt;code class=&quot;highlighter-rouge&quot;&gt;-vmargs&lt;/code&gt; line.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>A Credible Specification and Standards Body</title>
     <link href="http://njbartlett.name/2010/10/23/credible-standards-organisation.html"/>
     <updated>2010-10-23T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/10/23/credible-standards-organisation</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Doug Lea &lt;a href=&quot;http://gee.cs.oswego.edu/dl/html/jcp22oct10.html&quot;&gt;says that&lt;/a&gt; “the JCP is no longer a credible specification and standards body”. He’s probably right.&lt;/p&gt;

&lt;p&gt;However, a credible specification and standards body &lt;strong&gt;does&lt;/strong&gt; exist in the Java universe. I will leave its identity as an exercise, but let me just point out a couple of its nicer characteristics.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It produces &lt;strong&gt;fantastic&lt;/strong&gt; quality specifications.&lt;/li&gt;
  &lt;li&gt;It has worked effectively for over ten years as a collaboration forum for competing companies.&lt;/li&gt;
  &lt;li&gt;Oracle is a very active member, but Oracle doesn’t own it. Indeed, all the full members have exactly the same rights.&lt;/li&gt;
  &lt;li&gt;All its specifications are open, and come with a non-assert patent pledge from the members.&lt;/li&gt;
  &lt;li&gt;TCKs are freely available to open source projects, and the majority of the RIs are in open source already.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, it’s not without problems. The biggest is that membership dues are too high for small companies or academic institutes, and there is not yet a useful class of membership for individuals. But to be fair, if you pay your money then you can have the same rights (and responsibilities) as Oracle, IBM, SAP, VMWare and the rest.&lt;/p&gt;

&lt;p&gt;To quote my Californian friends: I’m just sayin’.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Bndtools is Growing</title>
     <link href="http://njbartlett.name/2010/10/21/bndtools-is-growing.html"/>
     <updated>2010-10-21T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/10/21/bndtools-is-growing</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;&lt;a href=&quot;/bndtools_intro.html&quot;&gt;Bndtools&lt;/a&gt; is starting to gather momentum and attract a real community. The best thing about this from my point of view is that I have started to receive significant contributions.&lt;/p&gt;

&lt;p&gt;The biggest so far has come from Per Kristian Søreide of &lt;a href=&quot;http://comactivity.net/&quot;&gt;ComActivity&lt;/a&gt;. Per and his team are hugely experienced in OSGi and Eclipse, and they have developed a tool for releasing bundles into a repository, with in-depth analysis of compatibility and versioning. Essentially, it helps you to comply with the &lt;a href=&quot;http://www.osgi.org/wiki/uploads/Links/SemanticVersioning.pdf&quot;&gt;OSGi Semantic Versioning&lt;/a&gt; (PDF) guidelines.&lt;/p&gt;

&lt;p&gt;When you make changes to an API, the tool calculates whether those changes are backwards compatible for consumers, producers, both, or neither. It then adjusts the version numbers of each package accordingly. It also bumps the version number of your source &lt;code class=&quot;highlighter-rouge&quot;&gt;.bnd&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;packageinfo&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;For example, suppose I make my first release of a new API, version 1.0.0. Here is what the tool displays:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/bndtools-release-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now I add a method to the &lt;code class=&quot;highlighter-rouge&quot;&gt;AuctionService&lt;/code&gt; interface and release again:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/bndtools-release-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This tells me that I have made a change that is non-backwards compatible for producers, and therefore the “minor” version segment needs to be incremented. That is, I need to update from 1.0.0 to 1.1.0. Of course it also highlights the reason. If I were to make an even more drastic change such as deleting a method, the tool would tell me that I need to bump to version 2.0.0, indicating a breaking change for both consumers and providers.&lt;/p&gt;

&lt;p&gt;Using this tool, alongside bnd’s existing support for generating import ranges, means that (in theory) &lt;strong&gt;you should never have to manually maintain version numbers!&lt;/strong&gt; Now, that’s a pretty bold statement and we need to see how things works out in practice, but I strongly feel that version management is one of those extremely important — but also extremely tedious — tasks that can be performed far better by machines than by humans..&lt;/p&gt;

&lt;p&gt;The release feature is now included in the main Bndtools update site, so if you have already installed Bndtools, please update it via the Eclipse update manager.&lt;/p&gt;

&lt;p&gt;Many thanks to Per and his team! And thanks also to all the others who reported bugs and contributed fixes… please keep them coming.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>OSGi Readiness — Loading Classes</title>
     <link href="http://njbartlett.name/2010/08/30/osgi-readiness-loading-classes.html"/>
     <updated>2010-08-30T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/08/30/osgi-readiness-loading-classes</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;In my previous post on “OSGi Compliance”, I discussed the idea of making libraries ready for OSGi without depending on OSGi directly. In light of BJ’s comment I will refer from now on to OSGi “Readiness” rather than Compliance, as the latter term is easily confused with the concept of a framework implementation that complies with the OSGi specification.&lt;/p&gt;

&lt;p&gt;In each of these blog posts, I will state a requirement and then look at options for satisfying that requirement in an OSGi Ready way.&lt;/p&gt;

&lt;h2 id=&quot;problem-statement&quot;&gt;Problem Statement&lt;/h2&gt;

&lt;p&gt;You are developing a Java library, “Framework X”. Occasionally you must load and instantiate a class dynamically by name, where the name may originate from a configuration file or be passed into the framework as a parameter to an API call. You would like the framework to work cleanly both in OSGi and other environments, i.e. there must be no dependency on OSGi.&lt;/p&gt;

&lt;p&gt;For example, suppose we are implementing an O/R mapping framework similar to Hibernate, and the user has supplied a configuration file such as the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;or-mapping&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;class&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;org.example.domain.Event&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;table=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EVENTS&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;id&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;id&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;column=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EVENT_ID&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
   &lt;span class=&quot;nt&quot;&gt;&amp;lt;/class&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/or-mapping&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This tells our framework to create an instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.domain.Event&lt;/code&gt; for each row of the EVENTS table. Therefore we must dynamically load and instantiate the &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.domain.Event&lt;/code&gt; class.&lt;/p&gt;

&lt;h2 id=&quot;discussion&quot;&gt;Discussion&lt;/h2&gt;

&lt;p&gt;To dynamically load a class in Java we require &lt;strong&gt;two&lt;/strong&gt; things: the fully qualified name of the class, and a &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt; from which to request it. If we have both of these then we can trivially load a class irrespective of whether we are in OSGi or not.&lt;/p&gt;

&lt;p&gt;To reiterate: &lt;strong&gt;OSGi does not interfere with the standard Java class loading API&lt;/strong&gt;. If we have the fully qualified name of a class and a &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt; that knows of that class, then we can always load and instantiate the class.&lt;/p&gt;

&lt;p&gt;Problems arise only when we do not know the correct &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt;, and make the wrong guess about which one to use.&lt;/p&gt;

&lt;h3 id=&quot;first-wrong-guess-classforname&quot;&gt;First Wrong Guess: Class.forName()&lt;/h3&gt;

&lt;p&gt;Java provides us with a way to load a class without explicitly specifying a &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt;, using the single-argument version of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Class.forName()&lt;/code&gt; method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clazz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;org.example.domain.Event&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Since we don’t specify a &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt;, this method uses the loader that loaded the class in which the line of code appears. In other words, it uses the same loader that loaded the framework. In a traditional Java SE environment this usually works just fine, because both the framework and domain classes are probably installed as JARs on the classpath, and the classpath is loaded by a single &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt;, the so-called “system” loader.&lt;/p&gt;

&lt;p&gt;But in OSGi, the domain classes are likely to be supplied in a different bundle, because there is a clear modular separation between the O/R framework code and the domain model classes, and therefore they will be loaded by a different &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt;. We can still make it work if the package &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.domain&lt;/code&gt; is listed as an import of the framework bundle like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-make&quot; data-lang=&quot;make&quot;&gt;&lt;span class=&quot;nl&quot;&gt;Import-Package&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;org.example.domain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt; ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;However this is unsatisfactory because &lt;code class=&quot;highlighter-rouge&quot;&gt;Import-Package&lt;/code&gt; is statically defined, and a general-purpose O/R framework does not know in advance which domain packages it will need to import.&lt;/p&gt;

&lt;p&gt;(&lt;strong&gt;NB&lt;/strong&gt; there are a couple of other workarounds for this problem in the case that the framework code cannot be changed. These include: &lt;code class=&quot;highlighter-rouge&quot;&gt;DynamicImport-Package&lt;/code&gt;; shipping the domain classes as a fragment hosted by the O/R framework; and using the Equinox-only “buddy loading” feature. However all of these workarounds have their own severe problems, which I shall not discuss in depth here because the purpose of the post is to document how to best implement a framework such that hackish workarounds are &lt;strong&gt;not&lt;/strong&gt; required.)&lt;/p&gt;

&lt;h3 id=&quot;second-wrong-guess-thread-context-class-loader&quot;&gt;Second Wrong Guess: Thread Context Class Loader&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;Class.forName()&lt;/code&gt; approach fails not only in OSGi but also in other environments such as Java Enterprise Edition, for similar reasons. Because of this, another common pattern is to use the Thread Context Class Loader (TCCL), which was introduced relatively recently (i.e. Java 1.2):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;ClassLoader&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tccl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;currentThread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getContextClassLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Class&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clazz&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;org.example.domain.Event&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tccl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Some libraries use the TCCL exclusively, others use it as a last resort after failing to load from other candidate class loaders. Almost every library follows a different strategy because Java has provided almost no specification or guidance on when to use the TCCL… to quote a &lt;a href=&quot;http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html&quot;&gt;classic JavaWorld article&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Those class and resource loading strategies must be the most poorly documented and least specified area of J2SE.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Even in J (2)EE the specifications do not lay out precisely which set of classes should be visible through the TCCL. In practice, a J (2)EE application server is able to provide a sensible set of classes via the TCCL because the programming model is highly constrained: each application runs in an isolated silo, is not allowed directly to create threads or network sockets, and threads cannot cross application boundaries. Because it controls all the entry points, the application server can provide a TCCL that is appropriate for the running code.&lt;/p&gt;

&lt;p&gt;OSGi’s programming model is far less constrained. Bundles are free to create threads, to open network sockets, and to call APIs exposed by any other bundle. There is no way in Java to intercept a direct method call that happens to cross a bundle boundary, so the OSGi framework cannot ensure the TCCL is relevant to the current code. As a result, the TCCL is not defined by the OSGi specification, and it may be &lt;code class=&quot;highlighter-rouge&quot;&gt;null&lt;/code&gt;. Therefore, we cannot rely on the TCCL for anything.&lt;/p&gt;

&lt;h2 id=&quot;solutions&quot;&gt;Solutions&lt;/h2&gt;

&lt;p&gt;Now let’s discuss possible solutions. To be clear, all of the following suggestions are intended to supplement rather than replace existing approaches. &lt;strong&gt;If your framework is working in J2SE/J2EE with &lt;code class=&quot;highlighter-rouge&quot;&gt;Class.forName()&lt;/code&gt; or TCCLs then you should continue to use those approaches&lt;/strong&gt;. But, please provide additional options for runtime environments such as OSGi where those approaches fail.&lt;/p&gt;

&lt;p&gt;If you feel these suggestions are trivial or obvious — that is exactly the point. There is nothing complicated about making frameworks that work well in OSGi. Indeed, you may find you prefer using one of these patterns as they reduce the complexity and testing burden of your code.&lt;/p&gt;

&lt;h3 id=&quot;option-1--instance-factory&quot;&gt;Option 1 — Instance Factory&lt;/h3&gt;

&lt;p&gt;The first option is to avoid dynamic by-name class loading altogether. Although not always practical, it may be possible in some cases to allow clients to supply their own callback or factory to create objects as required.&lt;/p&gt;

&lt;p&gt;For example our O/R mapper could define the following interface:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DomainObjectFactory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createInstance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Clients could supply an instance of this factory when initialising a session, or we could wire it in with our favourite Dependency Injector. This has the advantage that clients can construct objects however they like, rather than placing restrictions on the permitted constructors in the domain classes.&lt;/p&gt;

&lt;p&gt;On the other hand it may be risky since a client factory implementation could return shared instances, whereas the framework expects new objects on each call to &lt;code class=&quot;highlighter-rouge&quot;&gt;createInstance()&lt;/code&gt;. So long as such requirements are documented, the framework should permit clients to do what they like.&lt;/p&gt;

&lt;h3 id=&quot;option-2--register-classes&quot;&gt;Option 2 — Register Classes&lt;/h3&gt;

&lt;p&gt;Another option is to add API for clients to register loaded classes in advance. This is best illustrated in client code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registerClassForTable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EVENTS&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;List&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;events&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createQuery&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;from Event&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here the client code has direct visibility of the &lt;code class=&quot;highlighter-rouge&quot;&gt;Event&lt;/code&gt; domain class, so it can use a class-literal to pass a &lt;code class=&quot;highlighter-rouge&quot;&gt;Class&lt;/code&gt; to the framework API. The framework can now use the supplied class whenever it reads from the EVENTS table.&lt;/p&gt;

&lt;p&gt;We can even register classes directly against their names:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registerClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;org.example.domain.Person&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The framework can use the registered class whenever it needs to create an instance of &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.domain.Person&lt;/code&gt;, but fall back on &lt;code class=&quot;highlighter-rouge&quot;&gt;Class.forName()&lt;/code&gt;/TCCL for unregistered names. No other changes are required in the framework.&lt;/p&gt;

&lt;p&gt;Note that with this option, the client loses some flexibility and control. By passing a class rather than instances, the client has no opportunity to construct objects in the way it wants them, but instead relies on the framework to construct them.&lt;/p&gt;

&lt;p&gt;This is not so bad in the running example of domain objects, but suppose we are talking about some kind of “service” object. Without control over instantiation, clients cannot make the service aware of its “environment” or “context”. Sometimes this forces us to use static fields, thread-local variables or other hack to get hold of our “context” after having been instantiated by a framework.&lt;/p&gt;

&lt;p&gt;If the framework allows pre-instantiated objects, then those objects can be pulled out of the OSGi service registry, a Dependency Injection container, or even generated on the fly. So when designing an API, please consider whether the framework really needs to take control of instantiation by requiring &lt;code class=&quot;highlighter-rouge&quot;&gt;Class&lt;/code&gt; objects — if not, at least allow the option of passing pre-instantiated objects.&lt;/p&gt;

&lt;h3 id=&quot;option-3--pass-the-loader&quot;&gt;Option 3 — Pass the Loader&lt;/h3&gt;

&lt;p&gt;This option is the conceptually the simplest, and also has the least impact on existing code: allow clients to pass a &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt; into your API. The appropriate time to do this is highly dependent on the nature of the API, but in the O/R mapper it might be done during initialisation of a session:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;n&quot;&gt;SessionFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createSession&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClassLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ... OR ...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setDomainClassLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClassLoader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To minimise the impact on existing code, this method can be overloaded with another version that takes no argument. Alternatively, clients could pass &lt;code class=&quot;highlighter-rouge&quot;&gt;null&lt;/code&gt; to indicate that the framework should attempt to find the right &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Again there is a loss of flexibility for clients since this solution assumes all classes can be loaded from one class loader, which may not actually be the case, but in practice it doesn’t create any real problems.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;p&gt;Although this post has been rather long-winded, the message is very simple: &lt;strong&gt;stop guessing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are writing a library that performs dynamic by-name class loading, do not make assumptions about which &lt;code class=&quot;highlighter-rouge&quot;&gt;ClassLoader&lt;/code&gt; to use.&lt;/strong&gt; Allow client code to specify a class loader, or perform its own class loading. By all means retain your &lt;code class=&quot;highlighter-rouge&quot;&gt;Class.forName()&lt;/code&gt; or TCCL-based lookups, but please provide an override for environments in which they will not work.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>OSGi Compliance Levels</title>
     <link href="http://njbartlett.name/2010/08/24/osgi-compliance-levels.html"/>
     <updated>2010-08-24T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/08/24/osgi-compliance-levels</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Almost every week, I hear about new and existing Java libraries or frameworks becoming “OSGi Compliant”. This makes me happy as it indicates the traction that OSGi is getting as a platform. The only problem is that “OSGi Compliant” could mean almost anything… and therefore it means precisely nothing.&lt;/p&gt;

&lt;p&gt;For example, many libraries can be easily used in OSGi even if they don’t provide an OSGi descriptor (i.e., a &lt;code class=&quot;highlighter-rouge&quot;&gt;MANIFEST.MF&lt;/code&gt; containing &lt;code class=&quot;highlighter-rouge&quot;&gt;Bundle-SymbolicName&lt;/code&gt; etc.), so long as they steer clear of certain problematic coding patterns such as classpath scanning, unconstrained use of &lt;code class=&quot;highlighter-rouge&quot;&gt;Class.forName()&lt;/code&gt; and so on. Such libraries could reasonably be termed “compliant”. But another framework may have been deeply integrated into OSGi so that it can make use of services, receive configuration through Config Admin, and so on.&lt;/p&gt;

&lt;p&gt;It seems that we need a vocabulary that will help us distinguish these two cases, and those in between. We need to define, at least informally, some kind of Beaufort Scale for levels of OSGi compliance (if you’re feeling uncharitable towards OSGi you may prefer to call it a &lt;a href=&quot;http://en.wikipedia.org/wiki/Schmidt_Sting_Pain_Index&quot;&gt;Schmidt Pain Index&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The purpose of the exercise would certainly not be to admonish authors of libraries that rate near the bottom of the scale, nor to congratulate those at the top. Rather, it would help authors to communicate the depth of their support for OSGi in a more precise way, and it would help the OSGi community communicate to library authors how they can make their products more useful to us.&lt;/p&gt;

&lt;p&gt;To get the ball rolling, here are my initial thoughts. I do this merely to invite feedback rather than to attempt to impose my own classification.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Level&lt;/th&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Notes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;-1&lt;/td&gt;
      &lt;td&gt;Non-compliant.&lt;/td&gt;
      &lt;td&gt;Difficult or impossible to use in OSGi. May be possible to use via an adaption layer or patching of the sources or binaries. For example, the library may rely on classpath scanning or invalid assumptions about the classloading hierarchy.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;/td&gt;
      &lt;td&gt;Neutral.&lt;/td&gt;
      &lt;td&gt;Ships as a plain (i.e., non-bundle) JAR, but can be used straightforwardly in OSGi if wrapped as a bundle or added to &lt;code class=&quot;highlighter-rouge&quot;&gt;Bundle-ClassPath&lt;/code&gt;.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;Compliant&lt;/td&gt;
      &lt;td&gt;Shipped as one or more OSGi bundles with correctly defined &lt;code class=&quot;highlighter-rouge&quot;&gt;MANIFEST.MF&lt;/code&gt;s. All dependencies are also Compliant and either shipped with the library or available separately from a repository. Package versions follow the &lt;a href=&quot;http://www.osgi.org/wiki/uploads/Links/SemanticVersioning.pdf&quot;&gt;Semantic Versioning guidelines&lt;/a&gt; (pdf warning).&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;For many libraries, there is no need to go any higher than level 1. The higher levels are applicable to frameworks, which are more complex and may feature extensibility through plug-ins, custom configuration, logging, etc. Obviously I would like to see &lt;strong&gt;all&lt;/strong&gt; libraries reach at least level 1, but the OSGi community needs to do more to make this easier.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Level&lt;/th&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Notes&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;OSGi-Assisted&lt;/td&gt;
      &lt;td&gt;The framework is aware of OSGi, either in its core or via optional modules. Areas of the framework that are open to extensibility can use services for this, in addition to other mechanisms. The framework can cope with service dynamics without restarting the JVM.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;OSGi-Powered&lt;/td&gt;
      &lt;td&gt;The framework is based on OSGi. It publishes services that may be used by other parts of our system. Its own services may be replaced by our own service implementations. It takes advantage of standard OSGi services such as Log Service, Config Admin, Event Admin, HTTP Service. However, despite all this it may still provide a way to run in non-OSGi environments.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;A key concern for many frameworks as they seek to rise this pyramid is to remain usable outside OSGi, which is a goal I support. There appears to be very little information available on how to develop frameworks that are able to take advantage of OSGi without introducing a hard dependency on it. This is something I hope to remedy in future posts.&lt;/p&gt;

&lt;p&gt;What do you think of this taxonomy? Is it useful, or a waste of time? Should there more levels, or fewer? Please comment below, or link to your own blog.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; &lt;a href=&quot;http://tux2323.blogspot.com/2010/08/osgi-bundle-quality-or-bundle.html&quot;&gt;Christian Baranowski blogged&lt;/a&gt; some thoughts about independent verification of bundle compliance. That’s a great idea, but my initial goal is less ambitious, i.e. simply to allow library authors to assert something meaningful about their level of OSGi compliance. I think that is a prerequisite before looking to verify those assertions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE 2&lt;/strong&gt; BJ makes some excellent points in the comments below, which I entirely agree with. Be sure to scroll down and take a look.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>OSGi Masterclass with Peter Kriens and Neil Bartlett</title>
     <link href="http://njbartlett.name/2010/08/16/osgi-masterclass-with-peter-kriens.html"/>
     <updated>2010-08-16T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/08/16/osgi-masterclass-with-peter-kriens</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;&lt;a href=&quot;http://www.osgi.org/blog&quot;&gt;Peter Kriens&lt;/a&gt; and I will be running an &lt;a href=&quot;http://www.aqute.biz/MasterClass/MasterClass&quot;&gt;OSGi Masterclass&lt;/a&gt; in Girona, Spain from the 13th to 15th October 2010.&lt;/p&gt;

&lt;p&gt;The course is intended to deepen your knowledge of all aspects of OSGi. It is very hands-on and will cover the following areas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;How to think in Services&lt;/li&gt;
  &lt;li&gt;Distributed OSGi&lt;/li&gt;
  &lt;li&gt;Configuration&lt;/li&gt;
  &lt;li&gt;Persistence&lt;/li&gt;
  &lt;li&gt;GUIs&lt;/li&gt;
  &lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The masterclass is preceded by an optional one-day introductory course on 12th October, for developers who need a refresher on some of the basics of OSGi. Both the introductory day and the masterclass are located in a beautiful &lt;a href=&quot;http://www.balneariovichycatalan.rolinesystem.com/home.asp&quot;&gt;hotel near Girona&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://www.rolinesystem.com/v6/upload/img_website/379c2588477b1b06fa08f6ab509c71d840a79e91835ce2ab953f79a78bce1319/Website1/Menu36/foto1.jpg&quot; alt=&quot;HOTEL BALNEARIO VICHY CATALAN&quot; title=&quot;HOTEL BALNEARIO VICHY CATALAN&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Girona airport (GRO) is a &lt;a href=&quot;http://www.ryanair.com/&quot;&gt;RyanAir&lt;/a&gt; hub and is therefore cheaply accessible from all over Europe.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.aqute.biz/MasterClass/MasterClass&quot;&gt;Full Details&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.regonline.com/register/checkin.aspx?EventId=881199&quot;&gt;Direct to registration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
   </entry>
 
   <entry>
     <title>Generic OSGi</title>
     <link href="http://njbartlett.name/2010/08/10/generic-osgi.html"/>
     <updated>2010-08-10T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/08/10/generic-osgi</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;The next version of the OSGi specification — Release 4.3 — will finally support Java Generics. Neither the specification nor the RFC working document are publicly available yet, but the new API has recently been &lt;a href=&quot;https://bugs.eclipse.org/bugs/show_bug.cgi?id=322007&quot;&gt;checked into&lt;/a&gt; Eclipse Equinox for all to see.&lt;/p&gt;

&lt;p&gt;The most noticeable changes are to do with services, naturally. Both the &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceReference&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceRegistration&lt;/code&gt; classes now have a single parameter for the service type, and there are new methods on &lt;code class=&quot;highlighter-rouge&quot;&gt;BundleContext&lt;/code&gt; that take &lt;code class=&quot;highlighter-rouge&quot;&gt;Class&amp;lt;S&amp;gt;&lt;/code&gt; to produce objects of those types. These new methods augment the old String-based methods that now return &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceReference&amp;lt;?&amp;gt;&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceRegistration&amp;lt;?&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the biggest single set of changes is on the &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceTracker&lt;/code&gt; class, which now takes &lt;strong&gt;two&lt;/strong&gt; type parameters, &lt;code class=&quot;highlighter-rouge&quot;&gt;S&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;T&lt;/code&gt;, where &lt;code class=&quot;highlighter-rouge&quot;&gt;S&lt;/code&gt; is the type of service being tracked and &lt;code class=&quot;highlighter-rouge&quot;&gt;T&lt;/code&gt; is the type of objects being produced.&lt;/p&gt;

&lt;p&gt;This split has always been an important aspect of &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceTracker&lt;/code&gt;, but it was not obvious before. When a tracker is used in its default form (i.e. without overriding or customising) the two type parameters are the same: we track a service of type &lt;code class=&quot;highlighter-rouge&quot;&gt;S&lt;/code&gt; and then typically call &lt;code class=&quot;highlighter-rouge&quot;&gt;getService()&lt;/code&gt; to get the current instance of type &lt;code class=&quot;highlighter-rouge&quot;&gt;S&lt;/code&gt;. But the call to &lt;code class=&quot;highlighter-rouge&quot;&gt;getService()&lt;/code&gt; in fact gives us whatever the tracker’s &lt;code class=&quot;highlighter-rouge&quot;&gt;addingService()&lt;/code&gt; method returns, and we can override that.&lt;/p&gt;

&lt;p&gt;So in a sense, &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceTracker&lt;/code&gt; is a &lt;strong&gt;transformer&lt;/strong&gt; for services.&lt;/p&gt;

&lt;p&gt;For example, the first code sample in my &lt;a href=&quot;/2010/08/05/when-servicetrackers-trump-ds.html&quot;&gt;previous post&lt;/a&gt; was a &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceTracker&lt;/code&gt; that transformed a service of type &lt;code class=&quot;highlighter-rouge&quot;&gt;IA&lt;/code&gt; into a &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceRegistration&amp;lt;IC&amp;gt;&lt;/code&gt;… but you would have had to read the code very carefully to realise that. The &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceRegistration&lt;/code&gt; type wasn’t even mentioned in the &lt;code class=&quot;highlighter-rouge&quot;&gt;addingService()&lt;/code&gt; method, so you needed to know that was the return type of &lt;code class=&quot;highlighter-rouge&quot;&gt;registerService()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is what the same code will look like in OSGi R4.3 (N.B. I haven’t actually compiled and tested this, but it should work):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ForeachA&lt;/span&gt;
             &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServiceTracker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServiceRegistration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ForeachA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BundleContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServiceRegistration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addingService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
	                               &lt;span class=&quot;n&quot;&gt;ServiceReference&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registerService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;removedService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServiceReference&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
                               &lt;span class=&quot;n&quot;&gt;ServiceRegistration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;unregister&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ungetService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Unfortunately this a little bit more verbose than last time but it is safer due to the lack of casts, and more importantly the purpose of the class is clearly stated on the first line, thanks to the type parameters.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>When ServiceTracker Trumps Declarative Services</title>
     <link href="http://njbartlett.name/2010/08/05/when-servicetrackers-trump-ds.html"/>
     <updated>2010-08-05T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/08/05/when-servicetrackers-trump-ds</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;I normally recommend using the Declarative Services (DS) specification for working with OSGi services, and in general I agree with the recommendation voiced by others such as &lt;a href=&quot;http://martinlippert.blogspot.com/2010/03/slides-on-osgi-best-and-worst-practices.html&quot;&gt;Martin&lt;/a&gt; and &lt;a href=&quot;http://www.slideshare.net/caniszczyk/osgi-best-and-worst-practices&quot;&gt;Chris&lt;/a&gt; that one should avoid programming against the OSGi APIs.&lt;/p&gt;

&lt;p&gt;However I’d like to highlight a use case in which the good old OSGi &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceTracker&lt;/code&gt; API can produce code that is more readable and robust than anything we could achieve with DS.&lt;/p&gt;

&lt;p&gt;In DS, we declare components. A component can bind to services with either a unary reference, where the component binds to a single selected instance, or a multiple reference, where the component binds to all available instances. However the component itself remains a singleton.&lt;/p&gt;

&lt;p&gt;For example, suppose we declare a component as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IC&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nd&quot;&gt;@Reference&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;unsetA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This component binds to the service “IA” with a unary reference. If there are three instances of IA available then the component will bind as follows:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/ds-bind-unary.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Alternatively if we declare the component like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nd&quot;&gt;@Reference&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;multiple&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;unsetA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then the bind will look like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/ds-bind-multi.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But here is a binding that we cannot achieve in DS (at least, not declaratively):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/bind-per.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Fortunately the ServiceTracker code for this is actually quite simple. Suppose we want to create one instance of C for each available instance of IA, and also register those C instances as services under the IC interface. We assume that the C class has a public constructor that takes a parameter of type IA. Here is the complete code (excluding imports and package declaration):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ForeachA&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServiceTracker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ForeachA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BundleContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addingService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServiceReference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;registerService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt;
                                       &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;removedService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServiceReference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ServiceRegistration&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServiceRegistration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;svc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;unregister&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ungetService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Of course, we &lt;strong&gt;could&lt;/strong&gt; have achieved this with DS, by writing a component to manage C instances. We would have had to keep track of the instances of IA and the corresponding Cs and ServiceRegistrations, remembering to watch out for concurrency issues. If we were to go that route then we would essentially have reinvented ServiceTracker inside a DS component. The code above is much easier and less error-prone to write.&lt;/p&gt;

&lt;p&gt;Things get even more interesting if we need to reference &lt;strong&gt;two&lt;/strong&gt; service types, IA and IB, such that one instance of C is created for each combination of an IA and an IB, i.e.:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/bind-per-combine.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To do this in DS is very hard — think about all the things we must keep track of to ensure that we create a C for every IA and every IB irrespective of whether an IA or an IB appears first… and now think about making it thread-safe!&lt;/p&gt;

&lt;p&gt;However we can implement this pattern quite easily by chaining together a pair of ServiceTrackers. Here is the code, note that we are reusing the &lt;code class=&quot;highlighter-rouge&quot;&gt;ForeachA&lt;/code&gt; class from above but adding to it a constructor parameter of type IB:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ForeachB&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ServiceTracker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ForeachB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BundleContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addingService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServiceReference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;IB&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ForeachA&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreachA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ForeachA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;foreachA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreachA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;removedService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServiceReference&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ForeachA&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foreachA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ForeachA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;foreachA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ungetService&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that while using ServiceTracker necessarily means having a dependency on the OSGi APIs, it’s possible to completely isolate our usage of those APIs from our business logic. The class C is a POJO and receives instances of IA and IB through its constructor, so it remains useable and testable outside of an OSGi environment.&lt;/p&gt;

&lt;p&gt;In summary, there are still use cases where the low-level OSGi APIs such as ServiceTracker have an advantage over abstractions such as Declarative Services. I would like to see future versions of the DS specification support this specific use case, but I anticipate that will be difficult because of other things in the spec like Component Factories and factory configurations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATED&lt;/strong&gt;: Heiko Seeberger pointed out that the null-checks in my &lt;code class=&quot;highlighter-rouge&quot;&gt;addingService&lt;/code&gt; methods were not needed. This makes the code even more concise… thanks Heiko!&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>The Eclipse/Java 6u21 Blame Game</title>
     <link href="http://njbartlett.name/2010/07/29/eclipse-java6u21-blame-game.html"/>
     <updated>2010-07-29T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/07/29/eclipse-java6u21-blame-game</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;Ed Burnette published an &lt;a href=&quot;http://www.zdnet.com/blog/burnette/oracle-rebrands-java-breaks-eclipse/2012&quot;&gt;informative article on ZDNet&lt;/a&gt; about the recent incompatibility problem with Eclipse and Java 6 update 21. Unfortunately the comments contain a lot of nasty accusations and finger-pointing, with people variously blaming Oracle or Eclipse or both for the mess… and even Ed’s article title seems a trifle unfair on Oracle.&lt;/p&gt;

&lt;p&gt;To address those who accuse Eclipse of inappropriately using an internal variable, consider for a moment why this was done. Here are the facts:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The Sun JVM as shipped does not allow enough PermGen memory for a large application such as Eclipse to run. Incidentally many server applications also need more PermGen than is available by default.&lt;/li&gt;
  &lt;li&gt;There is no standard option to expand the PermGen. The option on the Sun JVM is &lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:MaxPermSize&lt;/code&gt; but the “XX” part indicates this option is specific only to the Sun JVM and is not available on other JVMs such as JRockit, IBM J9 etc. In fact using it with those JVMs can cause them to simply emit an error and exit.&lt;/li&gt;
  &lt;li&gt;Therefore Eclipse needs to detect whether it is on the Sun JVM specifically before it adds the &lt;code class=&quot;highlighter-rouge&quot;&gt;-XX:MaxPermSize&lt;/code&gt; option. This cannot be done in Java because by the time the JVM has started it is too late, so it has to be done in the native launcher executable, i.e. eclipse.exe, which is coded in C. At this point the Java system properties are not yet available, but the properties in the exe/dll file &lt;strong&gt;are&lt;/strong&gt; visible.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So I don’t think Eclipse has done anything particularly wrong here. Neither has Oracle, there was no reasonable way for them to know that a simple rebranding would cause such a problem, and they responded very quickly to fix it.&lt;/p&gt;

&lt;p&gt;Of course the fix is only a temporary one, as Oracle are going to want to change that variable eventually. So rather than pointing fingers, perhaps the Java community could try to come up with a real long-term solution. Such as a way to manage the JVM’s memory from within the JVM… or getting rid of the cursed PermGen altogether?&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Bndtools Now Available in Eclipse Marketplace</title>
     <link href="http://njbartlett.name/2010/07/20/bndtools-now-in-eclipse-marketplace.html"/>
     <updated>2010-07-20T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/07/20/bndtools-now-in-eclipse-marketplace</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;&lt;a href=&quot;/bndtools.html&quot;&gt;Bndtools&lt;/a&gt; — the OSGi development environment for Eclipse based on &lt;a href=&quot;http://www.aQute.biz/Code/Bnd&quot;&gt;Bnd&lt;/a&gt; — can now be installed from the Eclipse Marketplace. This is substantially easier than the traditional install procedure for Eclipse plug-ins, which involved copying and pasting an update site URL ino the Update Manager.&lt;/p&gt;

&lt;p&gt;Eclipse Marketplace client is available in all of the Eclipse 3.6 distribution packages except for the so-called “Eclipse Classic” distribution… if you are running Eclipse Classic then I strongly recommend installing the Marketplace client – this can be done in the usual way from the Helios update site.&lt;/p&gt;

&lt;p&gt;To install Bndtools, open the Help menu in Eclipse and select &lt;em&gt;Eclipse Marketplace&lt;/em&gt;. If this is the first time you have used it you may have to select your solution catalog as &lt;em&gt;Eclipse Marketplace&lt;/em&gt; (rather than &lt;em&gt;Yoxos Marketplace&lt;/em&gt; or any of the other catalogs that may appear in the future) and click Next. Then in the search field type “bndtools” (just “bnd” will work also) and click Go:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/eclipse-marketplace-bndtools.png&quot; alt=&quot;Eclipse Marketplace Client&quot; /&gt;&amp;lt;/img&amp;gt;&lt;/p&gt;

&lt;p&gt;Now click the Install button to the right of the Bndtools entry and follow the rest of the on-screen instructions. These include accepting the licence (of course) and accepting the fact that the plug-in is unsigned (I would love to get rid of this warning, but the price for a code-signing certificate is quite outrageous).&lt;/p&gt;

&lt;p&gt;The really neat thing about Marketplace Client is how easy it is to _un_install a plug-in. While I hope you find Bndtools useful enough to keep it around, it’s good to know that it can be removed painlessly if things don’t work out. Just reopen the Marketplace Client, select the Installed tab and click the Uninstall button next to Bndtools (and any other plug-ins that might be cluttering up your SDK):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/eclipse-marketplace-bndtools-uninstall.png&quot; alt=&quot;Eclipse Marketplace Client -- Uninstalling&quot; title=&quot;Don't do it!&quot; /&gt;&amp;lt;/img&amp;gt;&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>Multiple Component Instances with OSGi Declarative Services</title>
     <link href="http://njbartlett.name/2010/07/19/factory-components-in-ds.html"/>
     <updated>2010-07-19T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/07/19/factory-components-in-ds</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;p&gt;When we define a component using OSGi Declarative Services (DS), by default we are defining a singleton. For example using the Bnd annotation syntax we can define a component as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyComponent&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyInterface&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	
	&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
	
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This produces the following XML declaration to be used by the DS runtime:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;component&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'org.example.MyComponent'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;implementation&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'org.example.MyComponent'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;service&amp;gt;&lt;/span&gt;
		&lt;span class=&quot;nt&quot;&gt;&amp;lt;provide&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;interface=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'org.example.MyInterface'&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;nt&quot;&gt;&amp;lt;/service&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/component&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;At runtime one instance of the &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.MyComponent&lt;/code&gt; class is created and registered as a service under the &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.MyInterface&lt;/code&gt; interface. So far so good. But what if we want more than one of them?&lt;/p&gt;

&lt;p&gt;Well, this is possible but it begs the obvious question: “how many do you want?”. We need a way to communicate to the DS runtime how many instances to create. Typically this information is not available to use at build time, so we cannot simply declare it in the annotations or XML. We need a dynamic way to control the number of instances.&lt;/p&gt;

&lt;p&gt;If you have ever read the DS specification then you may be thinking that so-called “factory components” are the answer to this conundrum. Sorry but they are not… factory components are mostly a red herring… while they do have their uses, these are a lot more limited than they at first appear.&lt;/p&gt;

&lt;p&gt;The real answer is to take advantage of DS’s built-in integration with the Configuration Admin service. Recall that if we use Config Admin to create a configuration record with a “Persistent Identity” (or “PID”) matching the name of our component – in this case &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.MyComponent&lt;/code&gt; – then the component can receive the data in that configuration record simply by declaring an activation method like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyComponent&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyInterface&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Activate&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;A potential problem with this component is that it will &lt;em&gt;always&lt;/em&gt; be created, even if no configuration record is available. In many cases it’s fine to create a component in the absence of configuration data – the component should simply use defaults for the configuration values. However in other cases this won’t work because no reasonable default values exist. To address this problem, Declarative Services version 1.1 (included in OSGi Release 4.2) added a new “configuration policy” attribute:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configurationPolicy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyComponent&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyInterface&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Activate&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now the component will only be created if a configuration record with the PID &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.MyComponent&lt;/code&gt; exists.&lt;/p&gt;

&lt;p&gt;We have successfully tweaked the cardinality of the component from “always exactly one” to “zero or one”… and in fact this component now already supports “zero to many”. Instead of creating a single configuration record with a PID of &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.MyComponent&lt;/code&gt;, we can create multiple records with a “factory PID” of &lt;code class=&quot;highlighter-rouge&quot;&gt;org.example.MyComponent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we do this, and if the component has a configuration policy of “required” as shown above, then we will get multiple instances of the component, with each instance potentially receiving different configuration data. Perfect! DS will continue to maintain all the service references in our component of course.&lt;/p&gt;

&lt;p&gt;If you have not used Configuration Admin before and are unsure how to create configuration records, then take a look at &lt;a href=&quot;http://felix.apache.org/site/apache-felix-file-install.html&quot;&gt;Apache Felix FileInstall&lt;/a&gt;, which polls a directory for configuration files with the .cfg extension. It works on Equinox and Knopflerfish in addition to Felix.&lt;/p&gt;
</content>
   </entry>
 
   <entry>
     <title>OSGi and How It Got That Way</title>
     <link href="http://njbartlett.name/2010/03/07/osgi-and-how-it-got-that-way.html"/>
     <updated>2010-03-07T00:00:00+00:00</updated>
     <id>http://njbartlett.github.com/2010/03/07/osgi-and-how-it-got-that-way</id>
     <content type="html" xml:base="http://njbartlett.github.com/">&lt;blockquote&gt;
  &lt;p&gt;…some of you may have had occasion to run into mathematicians and to wonder therefore how they got that way. Here in partial explanation perhaps is the story of the great Russian mathematician Nikolai Ivanovich Lobachevsky. — Tom Lehrer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Probably the most common complaint against OSGi is that it is too complex. For example, quoting Reza Rahman of Caucho:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;From a personal standpoint, I did explore OSGi with an open mind. To my dismay, what I found is a very complex, low-level specification that needs a lot of evolution/abstraction to be adapted to be digestible to most enterprise Java environments. It also seems quite overkill for most realistic enterprise needs. Jigsaw in comparison feels much more “clean room”, Java-centric, compact and easy to understand.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Honestly, this complaint always makes me scratch my head a little. If I imagine for a moment that OSGi does not exist and I have been entrusted with the task of designing a new module system for the Java Platform, then the most sensible set of requirements for such a module system lead directly to OSGi as pretty much the most simple possible solution that satisfies those requirements!&lt;/p&gt;

&lt;p&gt;Is this just a failure of my imagination? Or is it perhaps a case where Einstein’s Razor (“things should be as simple as possible, but no simpler”) trumps Ockham’s?&lt;/p&gt;

&lt;p&gt;On the other hand, I accept that OSGi may not appear particularly simple at first glance, especially if you are not aware of how it got that way. Therefore in this blog post I have attempted to walk through the above thought-experiment of designing OSGi from scratch. I will gloss over a lot of detail of course. I had also intended to perform a similar analysis on Jigsaw, but this post is already a screed of nearly Yeggian proportions, so I will save Jigsaw for a subsequent post.&lt;/p&gt;

&lt;p&gt;So without further ceremony, just how did OSGi get that way?&lt;/p&gt;

&lt;h2 id=&quot;module-separation&quot;&gt;Module Separation&lt;/h2&gt;

&lt;p&gt;Our first requirement is to cleanly separate modules so that classes from one module do not have the uncontrolled ability to see and obscure classes from other modules. In traditional Java the so-called “classpath” is an enormous list of classes, and if multiple classes happen to have the same fully-qualified name then the first will always be found and the second and all others will be ignored. This is not as unusual a problem as it may appear; it’s quite common if you have a lot of libraries that depend on other libraries. Obscuration is an absolute killer because it can lead to weird errors such as LinkageError, IncompatibleClassChangeError, etc. In fact if we see those errors, we are lucky! If we are unlucky then our system will just quietly do the wrong thing, irrespective of all the up-front testing we may have done before deployment.&lt;/p&gt;

&lt;p&gt;The way to prevent uncontrolled visibility and obscuring of classes is to create a class loader for each module. A class loader is able to load only the classes it knows about directly, which in our system would be the contents of a single module (though it can also choose on a class-by-class basis to ask another class loader to supply the class instead — this is known as delegation). Once we do this, each module contains the code that it needs to work, and classes developed together are guaranteed to obtain the classes they expect, even if another module in the system has heavily overlapping fully-qualified class names.&lt;/p&gt;

&lt;h2 id=&quot;getting-back-together&quot;&gt;Getting Back Together&lt;/h2&gt;

&lt;p&gt;If we stop here then modules will be completely isolated and unable to communicate with each other. To make the system practical we need to add back in the ability to see classes in other modules, but we do it in a careful and constrained way. At this point we input another requirement: modules would like the ability to hide some of their implementation details.&lt;/p&gt;

&lt;p&gt;In Java there is a missing access modifier between protected/default and public. If I am writing a library and I wish one of my classes to be used by other packages in my library, I must make the class public. But then the class is visible to everybody, including clients external to my library; those clients can now use my internal parts directly. We would like to have a “module” access level, but the problem today is that the javac compiler has no idea where the module boundaries lie, so it cannot perform any checks against such a access modifier. In fact the existing “default” access modifier is also broken because it is supposed to offer access only to members of the same “runtime package” (i.e., a package as loaded by a particular class loader), but again javac has no idea what class loaders might exist at runtime. In this situation, javac punts: it allows the access even though it may result in IllegalAccessErrors later.&lt;/p&gt;

&lt;p&gt;The solution we choose in our module system is to allow modules to “export” only portions of their contents. If some part of a module is non-exported then it simply cannot be seen by other modules. But what should be the default? Should we export everything except for some explicitly hidden parts, or should we hide everything except for some explicitly exported parts? Choosing the latter seems to result in more clarity: we can easily look at the export list to determine the visible parts, i.e. the “surface area”, of the module.&lt;/p&gt;

&lt;p&gt;Notice that I have not yet specified what exactly is exported… that is deliberate, please bear with me.&lt;/p&gt;

&lt;p&gt;What’s the opposite of exporting? Importing, of course. A module that wants to use code from another module can import from it. Now we have another choice… should we import everything that is exported by the other module, or should we import just the parts of it that we need? Again we choose the latter since it results in more clarity: the important thing is what we are importing, not whom we import from.&lt;/p&gt;

&lt;h2 id=&quot;a-strained-shopping-analogy&quot;&gt;A Strained Shopping Analogy&lt;/h2&gt;

&lt;p&gt;This point about imports is very important, so I will digress for a moment into a hopefully humourous, if somewhat exaggerated, analogy about shopping.&lt;/p&gt;

&lt;p&gt;My wife and I have different approaches to shopping. I regard it as an onerous chore. When I must purchase something, I find a shop (or group of shops) that sells the items I need and I buy just those items and take them home. I don’t care which shop(s) I visit so long as I get the items I need.&lt;/p&gt;

&lt;p&gt;In contrast, my wife goes to a shop she likes and basically buys everything in that shop.&lt;/p&gt;

&lt;p&gt;Obviously I believe my approach is superior, because my wife has no control over what she brings home. If her favourite shop du jour changes its inventory then she ends up with different stuff… certainly lots of stuff she doesn’t need and perhaps missing some of the stuff she really does need.&lt;/p&gt;

&lt;p&gt;It gets even worse… sometimes she ends up with an item that will not work on its own, because it has a dependency on something else, like batteries perhaps. So she has to go shopping again for batteries, and of course ends up buying the entire contents of the battery shop. Straining the analogy a little now, we could imagine that something else acquired from the battery shop also depends on something else, so she makes yet another trip to another shop, and another, purely to satisfy the requirements of a bunch of items that were not even needed to begin with! This problem is known as “fan-out”.&lt;/p&gt;

&lt;p&gt;Hopefully the analogy with a module system is clear. The pathological shopping behaviour is equivalent to a system that forces us to import everything from the modules we declare a dependency on. When importing, we should import what we actually need to use, irrespective of where it comes from and ignoring all the things that happen to be packaged alongside it. We see the fan-out problem acutely when using the Maven build tool, which supports only whole-module (i.e. “buying-the-whole-shop”) dependencies, and as a result must download the entire Internet before it can compile a 200-byte source file.&lt;/p&gt;

&lt;h2 id=&quot;granularity-of-exports-and-imports&quot;&gt;Granularity of Exports and Imports&lt;/h2&gt;

&lt;p&gt;What should be the granularity of the things that we import and export from modules? There are many levels of granularity in Java due to the various nesting levels: methods and fields are nested in classes, which are nested in packages, which are nested in modules or JAR files.&lt;/p&gt;

&lt;p&gt;It shouldn’t be too hard to see that the sharing level should not be methods and fields. It would be simply insane to export some methods of a class but not others. Not only this, but we could write some methods/fields of a class in one module and some methods/fields in another module! Imagine writing the lists of exports and imports for every method that we wished to share across a module boundary. The complexity of checking this and diagnosing problems at runtime would be horrible, and lots of things would break because classes are just not designed to be split apart at runtime.&lt;/p&gt;

&lt;p&gt;At the other extreme, the sharing level should not be whole modules because then modules would not be able to hide parts of their implementation, and importers would routinely suffer from bought-the-whole-shop syndrome.&lt;/p&gt;

&lt;p&gt;So the only sane choices are classes and packages… and frankly, choosing classes just isn’t all that sane. Though not as bad as methods/fields, classes are too numerous and too heavily dependent on other classes in the same package for it to be sensible either to list classes as our imports and exports or to split some classes of a package into one module and other classes of the same package into another module.&lt;/p&gt;

&lt;p&gt;As a result, OSGi chooses packages. The contents of a Java package are intended to be somewhat coherent, but it is not too onerous to list packages as imports and exports, and it doesn’t break anything to put some packages in one module and other packages in another module. Code that is supposed to be internal to our module can be placed in one or more non-exported packages.&lt;/p&gt;

&lt;p&gt;What we lose is the ability to handle so-called “split-packages” cleanly. In OSGi, packages are the fundamental unit of sharing: when you import a package, you get the whole of a package as exported by one module but NO other. There are some strategies for dealing with legacy libraries that insist on smearing the contents of a package across many modules, but it is far better to adjust the modules so that each package is exported in its entirely by only one module.&lt;/p&gt;

&lt;h2 id=&quot;package-wiring&quot;&gt;Package Wiring&lt;/h2&gt;

&lt;p&gt;Now that we have a model for how modules isolate themselves and then reconnect, we can imagine building a framework that constructs concrete runtime instances of these modules. It would be responsible for installing modules and constructing class loaders that know about the contents of their respective modules.&lt;/p&gt;

&lt;p&gt;Then it would look at the imports of newly installed modules and trying to find matching exports. Suppose module A exports package com.foo and module B imports the same package. The framework would notify B that it can obtain classes for the com.foo from module A — this is called wiring. Now when the class loader for B tries to load the class com.foo.Bar, it will delegate to the class loader for A. The process of wiring up imports for a whole module is known as resolution and if all imports are successfully wired then the bundle is resolved, which makes it fully available for use.&lt;/p&gt;

&lt;p&gt;An unexpected benefit from this is we can dynamically install, update and uninstall modules. Installing a new module has no effect on those modules that are already resolved, though it may enable some previously unresolvable modules to be resolved. When uninstalling or updating, the framework knows exactly which modules are affected and it will change their state if necessary. There are some additional details to make this work smoothly, for example if a module is doing something important before it is uninstalled or unresolved then we need to send it a notification so it can shutdown cleanly. So, dynamic modules in OSGi do not come for free, since there is no magic involved, but OSGi at least makes it possible.&lt;/p&gt;

&lt;p&gt;Some OSGi users prefer to avoid dynamic loading, and that is fine. It is not the most important feature of OSGi, but because it is unique to OSGi it tends to get a disproportionate degree of attention. Nevertheless, nobody will force you to use it, and you will still derive plenty of benefits from OSGi even if you never take advantage of dynamics.&lt;/p&gt;

&lt;h2 id=&quot;versions&quot;&gt;Versions&lt;/h2&gt;

&lt;p&gt;Our module system is looking good, but we cannot yet handle the changes that inevitably occur in modules over time. We need to support versions.&lt;/p&gt;

&lt;p&gt;How do we do this? First, an exporter can simply state some useful information about the packages it is exporting: “this is version 1.0.0 of the API”. An importer can now import only the version that is compatible with what it expects and has been compiled/tested against, and refuse to accept e.g. version 3.0.0. But what if the importer wants version 1.0.0 and only version 1.0.1 is available… the slightly higher version doesn’t sound like it should be a breaking change, so the importer should probably accept 1.0.1 as well as 1.0.0. In fact the importer should specify a range of versions that it will accept, which could be something like “version 1.0.0 through to 2.0.0 but excluding 2.0.0 itself“. The package wiring process supports this and will only wire up an import to an export where the exported version falls within the range specified by the import. For this to work, version numbers need to be ordered and comparable.&lt;/p&gt;

&lt;p&gt;How do we know that version 1.0.1 is not a breaking change against 1.0.0? Unfortunately we cannot for sure. OSGi strongly encourages, but cannot enforce, the following semantics on version numbers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Increments to the Major segment (the first) should be made for non-backwards-compatible changes&lt;/li&gt;
  &lt;li&gt;Increments to the Minor segment (the middle) should be made for feature enhancements that are backwards compatible.&lt;/li&gt;
  &lt;li&gt;Increments to the Micro segment (the last) should be made for bug-fixes that do not produce visible feature changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everybody stuck to these semantics then specifying import ranges for any module would be a breeze. Unfortunately the real world is not so simple, so we have to look carefully at compatibility issues when using any external library.&lt;/p&gt;

&lt;h2 id=&quot;packaging-modules-and-metadata&quot;&gt;Packaging Modules and Metadata&lt;/h2&gt;

&lt;p&gt;Our module system will need a way to package the contents of a module along with metadata describing the imports and exports into a deployable unit.&lt;/p&gt;

&lt;p&gt;Java already has a standard unit of deployment: the JAR file. JAR files may not be fully-fledged modules but they work just fine for moving around chunks of compiled code, so we have no need to invent something new. So the only question is, where should we put the metadata, i.e. the lists of imports and exports, versions and so on?&lt;/p&gt;

&lt;p&gt;Configuration formats seem to be strongly influenced by fads; if we designed our module system between 2000 and 2006 we would probably choose to put the metadata in an XML file somewhere in the JAR file. This would work but it has a number of issues: XML is not particularly efficient to process, especially when we must find it somewhere inside a JAR file and decompress it before parsing. A JAR is just a ZIP, so finding a particular file means reading to the end to find the trailing central directory, then jumping back to the offset indicated by the directory. In other words, we always have to read the whole JAR file, which is a pain for tools that might want to scan large directories containing many modules, for example to search for available modules to satisfy a dependency.&lt;/p&gt;

&lt;p&gt;XML is also barely editable by human beings; we need custom editing tools to do it reliably.&lt;/p&gt;

&lt;p&gt;On the other hand if we were designing after 2006 then our first impulse might be to use Java annotations. I’m a big fan of annotations when used appropriately, and it’s easy to see the attraction of putting something like @Export(version=”1.0.0”) on a package declaration in the Java source rather than maintaining it in a separate file. But wait a minute… the package declaration is repeated in every source file in the package; must we put the annotation on all of them??&lt;/p&gt;

&lt;p&gt;To address this problem, the Java Language Specification (JLS) suggests the use of a special source file named package-info.java. Now what about the metadata that does not belong to any specific package, e.g. the list of imported packages or the name and version of the module itself? This suggests we need another special source file called something like module-info.java.&lt;/p&gt;

&lt;p&gt;So far so good, but now consider how the module will be processed. Those special source files will be compiled to bytecode in package-info.class and module-info.class, so you can forget about opening up the JAR file in WinZip to take a squint at the metadata! Any module-scanning tool will not only have to read whole JAR files but also have to be able to process bytecode. And the runtime module system itself will have to create a class loader for the module immediately, just to read its metadata; as it turns out this eliminates a large class of optimisations that are possible if we can defer class loader creation until a class is actually loaded from the module.&lt;/p&gt;

&lt;p&gt;As it happens OSGi was designed before 2000, so it did choose either of these solutions. Instead it looked back at the JAR File Specification, where the answer is spelled out: META-INF/MANIFEST.MF is the standard location for arbitrary application-specific metadata. In the words of the specification: “Attributes which are not understood are ignored. Such attributes may include implementation specific information used by applications.”&lt;/p&gt;

&lt;p&gt;MANIFEST.MF is designed to be efficient to process, and it is faster than XML, at least. It is somewhat readable; at least as readable as XML, and obviously more readable than compiled Java bytecode. Also the standard jar command line tool always places MANIFEST.MF as the first entry in the JAR file, so tools can scan just the first few hundred bytes of the file in order to obtain the metadata.&lt;/p&gt;

&lt;p&gt;Unfortunately MANIFEST.MF is not perfect. For one thing it is quite hard to write by hand due to a rule requiring each line to be no longer than 72 bytes, which becomes problematic if one considers that a single UTF-8 character can be between 1 and 6 bytes. A better approach is to generate MANIFEST.MF using a template in an alternative format; the Bnd tool does this, and so do Maven’s Bundle Plugin and SpringSource’s Bundlor.&lt;/p&gt;

&lt;p&gt;In fact, Bnd even includes experimental support for processing annotations such as @Export on source code annotations. These may give us the best of both worlds: the convenience of annotations, combined with the efficiency and runtime readability/toolability of MANIFEST.MF.&lt;/p&gt;

&lt;h2 id=&quot;late-binding&quot;&gt;Late Binding&lt;/h2&gt;

&lt;p&gt;The final piece of modularity puzzle is late binding of implementations to interfaces. I would argue that it is a crucial feature of modularity, even though some module systems ignore it entirely, or at least consider it out of scope.&lt;/p&gt;

&lt;p&gt;It is well known that interfaces in Java can break the coupling between consumers and producers of functionality. By defining an interface that serves as the contract between a consumer and a producer, neither of them require direct knowledge of the other, so we can put them in different modules that do not depend on each other. Instead they will each have a dependency on the interface, which can live in a third module if we choose. The only question is how to supply instances of the interface to the consumer class, and the most common answer these days is with a Dependency Injection (DI) framework such as Spring or Guice.&lt;/p&gt;

&lt;p&gt;Therefore to complete our module system we could simply defer to an existing DI framework. We are seeking simplicity after all, and there can be nothing simpler than declaring a problem to be out of scope, to be solved by somebody else. However this is not quite satisfactory because the DI framework really needs to be aware of the module boundaries. The problem with a traditional approach to DI is that it tends to create huge, centralised configurations which cut across all modules. Peter Kriens calls this the “God Class” problem, in which one component knows everything about every module and requires them all to do its bidding (as an atheist I find this unsatisfactory, but even if you are a theist then I’m sure you agree that we should not create any more Gods than currently exist). These God Classes — or XML configurations — are fragile, difficult to maintain, and negate most of the benefits of separating our code into modules.&lt;/p&gt;

&lt;p&gt;Instead we should look for a decentralised approach. Rather than being told what to do by the God Class, let us suppose that each module can simply create objects and publish them somewhere that the other modules can find them. We call these published objects “services”, and the place where they are published the “service registry”. The most important information about a service is the interface (or interfaces) that it implements, so we can use that as the primary registration key. Now a module needing to find instances of a particular interface can simply query the registry and find out what services are available at that time. The registry itself is still a central component existing outside of any module, but it is not “God”… rather, it is like a shared whiteboard.&lt;/p&gt;

&lt;p&gt;We do not need to abandon DI, indeed it is still very useful: existing DI frameworks can be used to inject services into other services and to declaratively publish certain objects as services. The DI framework no longer directs the whole system, instead it is a utility employed within individual modules. We could even use multiple DI frameworks, e.g. Spring and Guice together in the same application, which might be useful if we want to integrate a third-party component that uses a different framework from our own preferred one. Finally, the service registry will have a programmatic API for publishing and lookups, but it will only be used for low-level work such as implementing a new DI framework.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Hopefully this explains in broad stokes the reasons why OSGi is the way it is. OSGi will still be accused of being complex, but I believe that any complexity that does exist is there to handle the corner cases in what I have described.&lt;/p&gt;

&lt;p&gt;Of course it has its warts. For example, versioning could stand to be improved, especially in the face of third-party libraries with weird versioning schemes. It’s still the right choice to assign meaning to version numbers, but more assistance needs to be available for managing versions and compatibility of APIs. Then there are the legacy libraries that make dodgy assumptions about the existence of a flat system classpath. In my opinion, any library that takes in a class name as a String and calls Class.forName() to obtain an object is broken, since it assumes that all classes are visible to all modules, which is simply not true in any kind of modular system. Unfortunately they cannot all be fixed overnight, so we need strategies to deal with such broken libraries. However they need to be dealt with in exceptional ways that do not compromise the rules of modularity for everybody else.&lt;/p&gt;

&lt;p&gt;Coming up next: the motivation and design of Jigsaw, along with a technical comparison of its features alongside those of OSGi. I also intend to point out where it may be appropriate for OSGi to borrow some ideas from Jigsaw.&lt;/p&gt;
</content>
   </entry>
 
 
</feed>

