Archives for posts with tag: design

I’ve been working on a little Java web framework [1] for an exploratory work project. I am building the framework and a sample app as a set of OSGi bundles to drastically reduce API surface area between components [2]. This also makes it easy to run my sample app directly within base Eclipse, using Eclipse’s built-in support for OSGi framework launches and a bundle-ized version of Jetty.

This configuration raises an interesting problem though, how do you inject the application code into the framework, since the framework obviously can’t statically depend on the application code, and OSGi will only let Java classes “see each other” [3] if one bundle makes a package (or packages) visible via an Export-Package manifest declaration (e.g. Export-Package: my.api.package) and another bundle declares an explicit dependency on that package via an Import-Package declaration (e.g. Import-Package: my.api.package)? In other words, how will you avoid hitting java.lang.NoClassDefFoundErrors when trying to load the application code via reflection?

I sure didn’t know. Luckily I have a good buddy here at IBM in Research Triangle Park named Simon Archer who is an OSGi and Equinox expert [4], so I ran the problem by him. He told me about an OSGi manifest declaration I had never heard of called DynamicImport-Package. My assumption that you can only get at code via explicit Import-Package declarations was actually wrong.

Simon explained that the way DynamicImport-Package works is that it basically allows a bundle to say “I want to be able to access any class that is part of an exported package in the runtime environment. So let’s say I have two bundles: bill.framework and bill.sampleapp. I want the code in bill.sampleapp to run inside the web framework implemented in bill.framework, but I obviously don’t want the bill.framework code to have a static (class-level) dependency on the bill.sampleapp code since the whole reason I’ve designed it as a framework is to allow build-time composition of arbitrary applications built on the framework [5]. So I put the following in bill.framework‘s MANIFEST.MF file:

DynamicImport-Package: *

Then in my Sample App bundle’s MANIFEST.MF file, I put my application class in a package [6] that I export to the OSGi environment:

Export-Package: bill.sampleapp.app

Now the framework is able to dynamically load the sample app via reflection:

// MyFramework.java
String appClassName = System.getProperty("bill.app.classname");
IApplication app = (IApplication)Class.forName(appClassName).newInstance();

Voilà!

Footnotes:

[1] I know, because what the world needs now is another Java web framework. But as I observed in a journal entry, every framework is evil, except mine.

[2] Note that the framework itself doesn’t use or depend on OSGi. I build the bundles into a set of simple JARs that can run as part of a JEE web app or as standalone Java application again using an embedded Jetty web server.

[3] For a great primer on building modular Java applications with OSGi, see the recent book “OSGi and Equinox: Creating Highly Modular Java Systems” by McAffer, VanderLei, and Archer.

[4] E.g. Simon co-wrote the book mentioned in [3]. He is “Archer” 🙂

[5] Yes, I know. Most people call this pattern “dependency injection”. For the full treatise, see Fowler.

[6] The fact that you have to export the package for the code that you want to dynamically load wasn’t immediate obvious and Simon and I spent approximately twenty minutes staring at the screen wondering why we were getting java.lang.NoClassDefFoundError even though we were using DynamicImport-Package: *. After some unfruitful Googling, we decided to check out some bundle details using the OSGi console in Eclipse. As we were looking at the details for the sample app, I got the at the time unintuitive idea to try exporting the Sample App package. Sure enough this fixed it. Simon and I had a bit of a debate about whether or not it made sense to have to export application code since this effectively declares the application code to be API, which seems wrong – i.e. typically an application sits on top of a stack of code and depends on lots of stuff, but nothing depends on it.

But eventually we came to a reason that makes perfect sense for exporting the application code: If you didn’t have to explicitly export the code, theoretically any OSGi bundle’s code could get access to any other bundle’s code simply by declaring DynamicImport-Package: * and loading random classes via reflection, defeating the whole purpose of the OSGi modularity system. So by requiring that the to-be-dynamically-loaded class be available to the environment via an explicit Export-Package declaration you are still playing by the “normal rules” and just using reflection rather than static instantiation to poof up objects.

Of course this means that you should minimize your API surface area for the application class, so I put mine in its own package and its only public methods are those from the framework interface that it implements.

Good fences FTW!

Update: I’ve created a test page for this scenario, but I haven’t had a chance to test it yet on my iPad.

In our Jazz UIs, we tend to use “hover previews” quite a bit. That is, if you hover over a link, after a second or so it will show a small preview of the resource at the other end [1]. Jazz style guide example below (copyright IBM).

This was always broken on the iPhone’s Mobile Safari browser because I couldn’t figure out how to perform a mouseover action on a mouse-less interface.

I just noticed that the iPad seems to support onmouseover. I believe I’ve observed the following behavior:

  • If a link has no “on mouseover” actions (e.g. hovers), a tap follows to the link.
  • If a link has an “onmouseover” action, a tap activates the onmouseover action and a double-tap follows the link.

Obviously this implies that you should provide visual indications to your user whether the links provide onmouseover actions or not. For the Jazz links with hover previews we immediately decorate the link on mouseover (different color, double-underline, with a small chevron) and if the user remains over the link for a second or two we then show the preview.

[1] I realize that onmouseover actions attached to links represent a UX minefield. A page with too many / too aggressive hover actions can feel like an actual minefield!

Between early 2006 and early this year, my team at IBM Rational and I built a framework for component-based Ajax development for use in the Rational Jazz platform. The framework’s capabilities aren’t the focus of this entry, so I’ll just list some of them briefly:

  • A nice component model based on OSGi bundles and the Dojo module system
  • Request-time “building” of many fine-grained JavaScript files into monolithic files for faster download based on the introspected relationships between the files – i.e. no developer effort required for fast code loading other than writing good application code
  • Making a subset of the Eclipse extension registry available in the web page and queryable via JavaScript APIs modeled off of the org.eclipse.core.runtime extension registry Java APIs, allowing for open-ended extensibility using the Eclipse extensibility model
  • A simple framework for demarcating UI states that made the back button, history, and page titles work seamlessly within the Ajax page, even when a user gesture resulted in crossing a component boundary (e.g. loading and displaying a new virtual “page” from a different component) [1]
  • Dynamic, transparent loading of missing code in response to a user gesture that required it

We did a fairly good job of keeping our Ajax framework decoupled from the rest of the Jazz Platform both for the purpose of design cohesiveness but also to allow for possible future use by teams who weren’t building full-blown application lifecycle management applications like Jazz SCM or Iteration Planning.

Over time, other IBM teams heard about some of our capabilities and saw the positive results in our Rational Team Concert web UIs [2] and contacted us to explore whether they could make use of our code in their products. Each conversation went like this:

  1. We gave a demo and talk about the capabilities and architecture of the framework
  2. The other team said “that’s really nice, that’s really useful, that would be great to have”
  3. The other team said “we’re not sure we want to live within your framework, we’ll get back to you”
  4. The other team didn’t get back to us

Initially this didn’t really bother me – after all my job was to deliver the foundation for our Jazz web user interfaces, not to create a general purpose Ajax framework for IBM, but as I’ve thought about it more over time and seen this anti-pattern from other teams and other frameworks, I’ve decided that we should make a conscious effort to make our useful functionality available as simple building blocks (in the form of libraries) and then provide frameworks that layer on top of these building blocks.

Let me take a step back and explain what I mean.

A library is a set of reusable functionality where your application uses parts of the library as necessary. For instance, most programming languages have a library for creating and manipulating dates. Frameworks also provide functionality to the application programmer, but instead of the application programmer making simple function calls, the framework runs the show and calls into the application at well defined hook points. For example, GUI frameworks provide ways to wire up code to run in response to users clicking on buttons.

Both the library and the framework provide useful functionality intended to make the application developer more productive. Though it’s dangerous to make a general statement, it feels to me that the big difference between the two is that frameworks generally provide more power, but require you to make a bigger commitment to the framework’s way of working, while libraries provide generally less power, but make few (if any) demands about how you structure your application.

What’s unfortunate is when you’ve got some useful bit of functionality that could be made available as a simple library but it’s only available in the context of a framework. This is where we were with our Ajax framework. This stuff is too abstract, so here’s an analogy: Imagine that you heard about a new refrigerator which provided every feature and characteristic you ever dreamed about having in a refrigerator. The catch however was that you couldn’t just buy the refrigerator – you had to move into a house on the other side of town that included the new refrigerator. After about 10 seconds of thought you realize that even though it’s the fridge of your dreams, you’re sure as hell not going to move into a new house across town in order to get it. This situation (switching back to software from refrigerators) is shown in the diagram below.

Useful building blocks locked inside a framework

Useful building blocks locked inside a framework

My recent realization (which seems obvious in hindsight) is that the useful functionality provided by frameworks and libraries need not be mutually exclusive. For instance, in our Ajax framework’s dynamic build system, rather than requiring applications to run within our framework to enjoy this capability, we could have created a simple callable library to perform dynamic optimization on a set of files, and then created a framework that simply used this same library. This approach is shown in the diagram below:

Useful building blocks used by a framework but also available independently of the framework

Useful building blocks used by a framework but also available independently of the framework

Over the past month or so we’ve been refactoring our Ajax framework to extract the useful building blocks into simple callable libraries and making the framework proper smaller by delegating to these libraries. We’ve done this in the hopes that our code will be useful to other IBM teams but as a result of the exercise, we’ve gained a deeper knowledge of our software and the software’s quality has improved as we’ve decoupled the framework aspects from the building blocks aspects.

Going forward, it’s my intention that our team will generally start with building blocks first and then consider if we should provide some higher-level framework that uses these building blocks. I only wish we had taken this approach from the beginning but you know, live and learn.

Footnotes

  1. This UI state management framework evolved into dojo.hash
  2. You can see our Jazz web UIs built on top of this framework in the development section of Jazz.net if you register.

Updates

Changed “other than writing good code” to “other than writing good application code”