Platinum Partner
netbeans,netbeans platform

Idioms for the NetBeans Platform: Injectable Lookup Factory

With this article I'm starting a series of posts that will hopefully last for a few months, about a set of idioms (= technology-specific patterns) for the NetBeans Platform. All the things that I'll be talking about have been used during the development of blueMarine (and its new cousin blueOcean), some learnt or derived by others' work, a few as my original contribution. After almost three years of work with blueMarine on the NetBeans Platform they seem mature enough to be talked about and maybe useful for others; but of course I hope there will be discussions here as patterns and idioms need many different perspectives from the community for consolidating.

While I suppose that most of readers have at least a bit of knowledge about the NetBeans Platform, I'll try to write short introductions to put things in context; also because patterns/idioms are here also to help us in making better designs and I think that many concepts could be useful even outside the NetBeans Platform. Consider also that some parts of the NetBeans Platform can be used in regular applications as well (such in the case of the idiom I'm presenting today).

I'll use a really informal style here, while I'll later replicate the post contents to the NetBeans Wiki, with a more structured "pattern catalog" scheme and incorporating feedback and improvements.

There will be another related series of posts that I'll be starting on DZone soon - focused on how I designed one of the most important components of blueMarine - and, for the record, I've submitted related talk proposals to JavaOne and Jazoon 2009.

So, let's start with the Injectable Lookup Factory.

Refreshing the Lookup API

The Lookup API is one of the more important things in the NetBeans Platform: it is simple and powerful for designing services with a good separation between interface and implementation. The essence of the Lookup API is - you bet - the Lookup class, which is used for searching objects:

Lookup lookup = ... // get a Lookup somewhere
MyClass myObject = lookup.lookup(MyClass.class);

and many times you'll be using the "default" or "global" Lookup, which acts a sort of application context:

MyClass myObject = Lookup.getDefault().lookup(MyClass.class);

Often MyClass is an interface (or abstract class) describing a service, that you are sure it has been implemented somewhere, but you don't want to know details about that; it could be even implemented in alternate, polymorphic ways (e.g. the real service and a mock for tests). In this form, the Lookup API is clearly used as a "service locator".

Lookups can search for concrete implementations in many different ways. One of the most common for the default lookup (but not only) is the META-INF/services mechanism: referring to the above example, you should have somewhere in your classpath the file:

META-INF/services/mypackage.MyClass

with a single line containing the name of the implementation class; for instance:

myotherpackage.MyClassImpl

For the record, you could even define multiple implementations (on multiple lines in the same file) or there could be multiple copies of that file in the classpath; in this case you might want to use lookup.lookupAll() for retrieving all of the results.

By default, the requested object is istantiated as a singleton; and of course implementations may be specified in a different module of the calling code (indeed, this is one of the cases that makes most sense).

But this is just scratching the surface: Lookup can be pretty usefuly if you create your own instances bound to your objects; for instance, model objects, representing some kind of data.

If you want some more simple examples about Lookup, Hulles has just published a good article on it.

A real world scenario

Let's sketch a small but complete example. Let's suppose we're dealing with media (photos, sounds, movies) and we have a MediaObject class representing them. Media have got some common features, such as the name of the file where the media is stored and the MIME type, and it makes sense to have methods such as getFile() and getMIMEType() on MediaObject. But, unfortunately, common behaviour stops here; for the rest, we could assume that:

  • I can create a visual preview (a thumbnail) for a photo and a movie
  • Sounds and movies are "streamable", that is they need to be reproduced over time (e.g. the viewer needs a pair of play / stop buttons).

One could model these capabilities (write down this term as it is very important) as follows:

This design is not the best thing that we can do and indeed it can be evil in function of how client classes will be written. We're using inheritance not only for polymorphic behaviours, as the three subclasses introduce new methods (violation of Liskov's substitution principle); thus clients calling specific methods need to be coupled with specific subclasses (while in good polymorphism you'd only need to couple with the base class). For instance, I can see bad stuff such as this easily coming out:

MediaObject mediaObject = ... // something

if (mediaObject istanceof MovieObject)
{
// set up a movie player
}
else if (mediaObject instanceof PhotoObject)
{
// set up a photo renderer
}
// etc...

which is the infamous if-else cascade, leading to cumbersome and hard-to-maintain code (for instance, should you introduce a new PDFObject, you'd need a new if-else branch).

You can improve things if you refer to interfaces rather than concrete subclasses:

MediaObject mediaObject = ... // something

if (mediaObject istanceof Streamable)
{
// set up a movie player
}
else if (mediaObject instanceof Previewable)
{
// set up a photo renderer
}
// etc...

as at least you're depending on concepts that are more abstract (you can e.g. have the PDFObject implementing Previewable, this making an existing if-else work). A big problem that you're not resolving is that you're pretending that a photo is always previewable and a movie is always streamable. What if you are dealing with a movie that you don't have the codec for? You might want still to deal with it - for instance, for cataloguing purposes - even though it's not possible to reproduce it. In other words, in a more flexible design the capabilities we're talking about are not necessarily properties of classes, but properties of objects (instances).

At this point, people usually talk about "using composition instead of inheritance" and Lookup can help here: let's create a private instance of Lookup for any instance of MediaObject and let's populate it with the relevant capabilities, as described by the following diagram (only the part related to PhotoObject has been fully drawn):

You shouldn't be worried by the fact that there are more classes in the design, as they are simpler and more decoupled than before.

For instance, PhotoObject can be implemented as:

public class PhotoObject extends MediaObject
{
@Nonnull
private final Lookup lookup;

public PhotoObject()
{
lookup = Lookups.fixed(new PhotoObjectStreamable(), new PhotoObjectPreviewable());
}

@Nonnull
public final getLookup()
{
return lookup;
}
}

For simplicity, the code in the example always creates the two capabilities; in the real world you should instantiate only those making sense for the specific PhotoObject instance you're dealing with.

The Lookups.fixed() in the previous code example is a utility method from the Lookup API that creates a new immutable Lookup containing the objects passed as parameters.

Now the client code can be rewritten as:

MediaObject mediaObject = ... ; 

Previewable previewable = mediaObject.getLookup().lookup(MediaObject.class);

if (previewable != null)
{
// set up a photo renderer
}

else
{
Streamable streamable = mediaObject.getLookup().lookup(Streamable.class);

if (streamable != null)
{
// setup a movie player
}

// etc...
}

This makes it even possible that, later in the project evolution, I decide that a sound is previewable too (for instance, by rendering the waveform).

Unfortunately, there's still the if-else cascade and it's even bigger: let's get rid of it too. Let's introduce a new capability named MediaRenderer:

public class MediaRenderer extends JComponent
{
...
}

and put it into the Lookup too, so everything boils down to:

MediaObject mediaObject = ... ;
MediaRenderer mediaRenderer = mediaObject.getLookup().lookup(MediaRenderer.class);

if (mediaRenderer != null)
{
// add it to the GUI
}

 

Note how this is much more elegant, readable, maintainable and extensible than the original code; we have really active, rich objects with better roles and responsibilities (it's not good when you have an object and client code must figure out things about it). Now you can add as many new media types as you want and, as soon as you provide them with a proper renderer, your application will work fine; the same holds for any other capability.

Since we're thinking of a highly modular application as the NetBeans Platform allows for, you could imagine of having alternate renderers, or cases in which the renderer is not there because you don't need it (e.g. the code is used in a web application which, of course, doesn't use Swing), or cases in which you use a totally different UI framework (e.g. Pivot in place of Swing) - and the client code still works:

 

But - I expect a strong objection now. Ok, the client code looks good, but what about PhotoObject? Since it is the one which creates the capabilities, PhotoObject now depends on them (including those related to the user interface, such as Swing!). A Model class depending on View classes doesn't really sound good and jeopardizes all of our dreams about modularity and flexibility (as it often happens, the devil is in details). Note that in the previous diagram I've put explicit navigation arrows and the capabilities needs to know - and depend on - PhotoObject, not the opposite.

The Injectable Lookup Factory idiom can help now in inverting the dependencies as required.

The Injectable Lookup Factory idiom

The idea is that PhotoObject has got a Lookup, but it shouldn't decide what capabilities to put (= create) into it. When you want to decouple the responsibility of creating some objects from the responsibility of deciding which objects to create, the GoF Factory (Method) pattern comes to the rescue. So, it should be not a surprise that we need a LookupFactory here:

 

Code can be checked out from svn co https://openbluesky.dev.java.net/svn/openbluesky/trunk/src/OpenBlueSky/CapabilitiesProvider -r 439

The first participant of the idiom is a CapabilitiesProvider:

public interface CapabilitiesProvider<T>
{
@Nonnull
public Class<T> getManagedClass();

@Nonnull
public Collection<? extends Object> createCapabilities (@Nonnull T owner);

@Nonnull
public Collection<? extends Lookup> createLookups (@Nonnull T owner);
}

Each instance of this class is able to find out which capabilities a certain object ("owner") of a given class ("managed class") should have.

Capabilities are usually returned as a generic collection of objects, but it might be useful to provide them as already-built Lookup instances filled with stuff - this just as a convenience, as in my experience, especially when composing objects, I've found myself with a Lookup already packed up - and it is useful to avoid to "unpack" a Lookup instance just to pack up a new one.

The InjectableLookupFactory implementation is this:

public class InjectableLookupFactory
{
public static Lookup createLookup (@Nonnull final Object owner,
@Nonnull final Lookup ... extraLookups)
{
final List<Lookup> lookups = new ArrayList<Lookup>();

for (final CapabilitiesProvider provider :
Lookup.getDefault().lookupAll(CapabilitiesProvider.class))
{
if (provider.getManagedClass().isAssignableFrom(owner.getClass()))
{
lookups.add(Lookups.fixed(provider.createCapabilities(owner).toArray()));
lookups.addAll(provider.createLookups(owner));
}
};

lookups.addAll(Arrays.asList(extraLookups));

return new ProxyLookup(lookups.toArray(new Lookup[0]));
}
}

A ProxyLookup is a utility class from the Lookup API that creates a new Lookup which contains the union of the contents of multiple existing Lookup instances - yeah, "proxy" is probably not the most appropriate name here.

That is, the smart idea is that CapabilitiesProviders are searched by the global Lookup; this is the part that introduces the real decoupling. Back to the original example, PhotoObject now just doesn't know which capability implementation should use to render itself, but in some other module of the application there is a CapabilitiesProvider implementation that does:

public class PhotoObjectPreviewCapabilityProvider implements CapabilitiesProvider<PhotoObject>
{
@Nonnull
public Class<PhotoObject> getManagedClass()
{
return PhotoObject.class;
}

@Nonnull
public Collection<? extends Object> createCapabilities (@Nonnull final PhotoObject owner)
{
return Collections.singletonList(new PhotoObjectPreviewRenderer());
}

@Nonnull
public Collection<? extends Lookup> createLookups (@Nonnull final PhotoObject owner)
{
return Collections.<Lookup>emptyList();
}
}

Now, the private Lookup in PhotoDataObject can be created as easily as:

public class PhotoDataObject extends MediaObject
{
@Nonnull
private final Lookup lookup = InjectableLookupFactory.createLookup(this);

@Nonnull
public final Lookup getLookup()
{
return lookup;
}
}

Please note that the design is so powerful that by just adding new modules to your existing application you are extending the functions of your objects.

For instance, blueMarine manages metadata for media by a specific factory class named Metadata which provides the proper getters and setters; this API is completely independent of the rest of the application and just "injects" instances of Metadata into model objects, so the client code to retrieve metadata is just:

MediaObject mediaObject = ...;
Metadata metadata = mediaObject.getLookup().lookup(Metadata.class);

if (metadata != null)
{
Object metadataItem = metadata.getSomething(); // etc
}

while MediaObject doesn't know anything about Metadata.

Indeed, Metadata itself is implemented in a similar way, so different kinds of metadata such as EXIF, IPTC, geotags etc... are managed by completely independent modules, and the real code is:

MediaObject mediaObject = ...;
Metadata metadata = mediaObject.getLookup().lookup(Metadata.class);

if (metadata != null)
{
EXIF exif = metadata.findOrCreate(EXIF.class); // equivalent to lookup()
}

and the new point is that Metadata doesn't know about EXIF, IPTC or whatever; somewhere, there are modules containing a PhotoObjectEXIFCapabilityProvider, MovieObjectEXIFCapabilityProvider, etc. This leads to a high number of modules with just a few small, focused classes with very limited couplings.

As a last word, recalling the hierarchy of MediaObject and subclasses, you could even give up completely with inheritance: avoid subclassing MediaObject and turn it into a generic container of capabilities.

In practice, blueMarine still keeps distinct subclasses, also because of some constraints put by the DataObject API of NetBeans, that I don't want to discuss now; but it's likely I'll be able to get rid of them in future refactorings.

One of the drawbacks of this idiom is that constructing an instance of MediaObject could take longer, since it will involve a scan of META-INF/services - while I don't have measured it the penalty so far, I don't see any macroscopic trouble; and in case of problems, I think that the search of CapabilitiesProviders could be just cached after the first run.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks
Tweet

{{parent.nComments}}