Regular InfoQ Java contributor Dr. Alex Blewitt has recently published a follow-up to last year’s "Eclipse 4 Plug-in Development by Example”. Called “Mastering Eclipse Plug-in Development,” the book, like its predecessor, is essentially a tutorial, but it assumes that you are already familiar with the basics of building plug-ins for the Eclipse IDE, and rapidly dives into some fairly advanced topics.
The first two chapters explore how developers can plug in to various parts of the Eclipse framework, building up an example of a news reader that works with both RSS and Atom feeds. Chapter 1 uses JFace - the set of Standard Widget Toolkit (SWT) based widgets that make up the Eclipse user interface - to create the basic news feed wizard. This is then integrated into the Common Navigator Framework, which is in turn used by the Package Explorer to provide a tree view of the project’s contents.
The second chapter introduces the Eclipse extension registry. This is commonly used in OSGi runtimes, but the author shows how it can also be used outside this environment, building a plug-in that allows other plug-ins to contribute functionality outside of the OSGi or Eclipse runtime.
The remainder of the book focuses primarily on OSGi. Chapter 3 provides an excellent introduction to OSGi services, something which is not generally covered in other Eclipse plug-in books. OSGi services can have multiple versions available at runtime, and can work in other OSGi environments such as Felix. The chapter includes a good comparison of Declarative Services, the original mechanism to instantiate services in a declarative fashion during OSGi runtime, and Blueprint, introduced a couple of minor versions later that does essentially the same thing.
Chapter 4 introduces the Gogo shell, embedded in Eclipse 4 and used by both Felix and Equinox. After exploring the syntax including variables, literals and functions, the author goes on to look at how to extend the capabilities of the console using both the osgi:addCommand that comes with Gogo, and by writing custom Java classes and registering them as OSGi services. Then Chapter 5 looks at how to load native code into an OSGi or Eclipse application, and how fragment bundles can be used to extend the capabilities of the framework.
Chapter 6 provides an excellent introduction to ClassLoaders, and how OSGi’s use of class loaders supports bundle separation. Since many libraries incorrectly assume there is only one ClassLoader per JVM, Blewitt also examines strategies to upgrade these libraries so that they can run in an OSGi environment.
Building an Eclipse plug-in, or indeed any OSGi-based application, involves breaking components into smaller, loosely-coupled, highly-cohesive modules. In Chapter 7 the author presents some of the common techniques, design patterns, and current best practices that can help in the sometimes difficult process of doing this.
The final chapters cover building reactive applications using the OSGi Event Bus, using Eclipse P2 to generate update sites, and how to write help files for Eclipse.
The book is clearly and concisely written, with well chosen examples that really help the reader's understanding of the various concepts under discussion. The majority of the book provides superb coverage of modularity, and in particular the OSGi framework that Eclipse itself uses. It also provides an excellent introduction to classloading.
InfoQ spoke to Alex to find out more about the book.
InfoQ: Did you always plan to write a follow up to the first book and, if not, what prompted you to do so?
Alex: After writing Eclipse 4 Plug-in Development by Example, I had intended to take a break from writing for a while; writing a book takes a lot of time, especially if you have a full-time job alongside. However, the first book was doing very well and the publishers asked me if I was interested in doing a more advanced book. I did have some ideas, especially around OSGi patterns, that I wanted to write about and the opportunity to follow up seemed too good to pass.
There were also some topics that weren’t covered in the original book due to space and level issues; for example, creating wizards through to update sites and help documentation isn’t something that simple plug-ins need. However, if you’re building a larger set of Eclipse plug-ins or want others to be able to build on top of those frameworks, then it is necessary to understand how the extension registry works and how to create custom extension points. There’s also the possibility to go a lot deeper in an advanced book, such as the classloading or OSGi service layer.
InfoQ: The book serves as an excellent introduction to OSGi, as well as providing a very good introduction to classloaders. Aside from Eclipse plug-in authors, are there other developers who you think would benefit?
Alex: OSGi is one of the most under-appreciated technologies of the last decade. For big Java services, it’s in many places, not to mention various IDEs. Adobe have a number of tools that are built upon OSGi, and large-scale systems like Liferay and Paremus are using it to power their platforms. For each of these, the focus is on modularity and decoupled services. We’re starting to see these aspects occurring in other platforms at the moment; the general trend to move to disparate REST services is such an example. The idea of managing code complexity through modularity is ultimately necessary - even the JDK is being modularised as we speak. But a side-kick of modularity is backwards compatibility, or at least, versioned compatibility. The majority of developers implicitly follow Semantic Versioning (see http://www.semver.org for more details) and the idea of not breaking backwards compatible clients is key. This still holds true whether you’re building Java services or using REST services to couple together many different languages; if you are no longer in control of deploying a monolithic unit, then you must take compatibility on board. Some languages, like Scala, view backwards compatibility as too high a price to pay, which is generally why you don’t see such a varied ecosystem of libraries as you do in Java.
Coming back to the question regarding the OSGi chapters - I think Eclipse specifically is heading in the direction of more OSGi services instead of static factory accessor methods. Understanding the OSGi model of services is key to seeing where Eclipse is going to rather than where it has been, and so should be required reading for Eclipse plug-in authors. However, the wider world of Java is moving towards modularity as well, and backwards compatibility has never been more important. There’s a lot that can be learned from the OSGi model, and that can benefit Java developers even if OSGi isn’t something they have investigated before. I hope I’ve written an introduction to how to get things done with OSGi rather than being too heavily opinionated on why others have been using it for decades.
As for classloaders, they are not often well understood by Java developers even if they’ve been using them transparently all along. A classloader provides two services; one is to create a Class from a sequence of bytes (loaded from somewhere; whether that’s a local or remote URL or a database or even generated dynamically), and the other is to partition the Class space into different sections. For example, if you deploy two web applications that use Log4J into a Tomcat or Jetty server, each web application will independently load the Log4J classes. So at runtime, the JVM actually has two LogFactory classes loaded; one which is visible to the first web application, and a second visible to the second web application. Even if there’s a static reference - such as returned by LoggerFactory.getLogger(Example.class) - then there will be two instances of the Logger class, one visible to each classloader. Although the Java language makes it appear that it’s a singleton, in fact only a naive Java developer would think that there’s only one per JVM. This allows, for example, logging levels to be different between different web applications, which can be quite useful if you want to debug a single application in a shared instance server. Part of the reason for writing the classloaders introduction is to explain how they work, because they’re a fundamental part of how all Java applications and application servers work, even if it’s not obvious.
InfoQ: It's never been clear to me why OSGi has both Declarative Services (introduced in version 4) and Blueprint (introduced in version 4.2) - they seem to serve a more-or-less identical purpose. Any idea why we ended up with both?
Alex: Both Declarative Services and Blueprint provide a way of performing auto-wiring of services and service dependencies, so from that perspective they are similar. Under the covers, the OSGi service model is used for both; they both look for services coming (and going) and use that to reconfigure the system dynamically.
Declarative Services is a little bit closer to the metal of the services runtime; DS waits until a service is needed and its dependencies are available before publishing the service. So if you were looking for a hypothetical CacheService, for example, it wouldn’t exist until the CacheService’s dependencies were met. This solves a lot of ordering problems that may be seen at startup; if it doesn’t make sense to have a CacheService until the backing layer is present, then you won’t see one.
Blueprint, on the other hand, publishes service proxies before the service implementation is available. They speculatively assume that a service will exist at some point in the future, so publish the CacheService ahead of time. When a client attempts to use it for the first time, it then tries to instantiate and satisfy any dependencies; and if they can’t be met, a runtime exception will be thrown.
The other difference with Blueprint is that the proxy you get handed back can be passed around to various different objects and persisted as a final member of a class; once you have a proxy, you’ll always use that proxy, even if the underlying service comes and goes. So for a developer who is not used to the dynamic nature of OSGi, it can be easier to integrate with Java code that doesn’t expect services to come and go. The Blueprint configuration is also heavily based on the Spring bean configuration files, which makes it easier to understand when migrating from Spring to a more dynamic OSGi model.
So as I said in my book, the Blueprint model is one that is easier to get started with if you are migrating from a Spring environment beforehand, because it’s loosely a copy-and-paste of the Spring configuration files and you’re done. If you’re not coming from a Spring background, then DS may be a simpler approach. In both cases though, you are expressing a service based on its dependencies and letting the system take care of the instantiation and wiring instead of trying to do everything manually. Ultimately they both use the OSGi service model under the covers, and like REST, it doesn’t matter how the service gets there as long as it uses the standard API to talk to it once it is there.
InfoQ: In the discussion of Blueprint you are somewhat critical of Gemini, given its dependency on Spring, whilst noting that it can be useful for Spring application developers migrating to OSGi. I wondered if you could expand on this a little. Does OSGi provide similar capabilities to Spring? Do you see the core of Spring as essentially legacy in an OSGi environment?
Alex: Both Gemini and Aries provide the Blueprint service, in the same way that Jetty and Tomcat both provide Servlet support. So in the same way that you can take a WAR and deploy it to either Jetty or Tomcat, you can deploy an OSGi application that uses Blueprint to an OSGi container that contains Gemini or Aries. When you consider equivalent bundles, one of the differentiating factors (all other things considered) is the set of dependencies that they require. In the case of Aries, there are 5 bundles (of which two are SLF4J logging bundles). For Gemini, there are 9 bundles that need to be installed, of which 6 are the Spring bundles. In addition, Spring is no longer built with OSGi metadata so it becomes necessary to post-process the bundles from a repository in order to be able to use it.
As for whether Spring is essentially legacy in an OSGi environment … there are a lot of good Spring-based projects that do a good job, and most of them interoperate with Spring context in some way. Spring did popularise dependency injection and move the goalposts from ‘how do I instantiate this bean’ to ‘please give me this bean’. OSGi does the same thing with services; the key difference is that the service can be dynamically removed, restarted, upgraded and even replaced on the fly. Of course, not every application needs that level of dynamism and Spring applications are generally built and deployed in a monolithic way, so it really depends what the end goal is. Although OSGi does lend itself well to the dynamic nature, some may find that the ability to partition and modularise the application is of greater benefit. I think I’d summarise it as saying Spring takes you to one level of application development - decoupled beans - but still with a monolithic view of deployment and configuration. OSGi takes over from where Spring leaves off in terms of being able to dynamically update configuration and have services reconfigure on the fly, instead of needing downtime to restart the application. This is especially useful in cloud or networked environments where distributed services can come into play.
I think ultimately it’s possible to outgrow the Spring container once you’ve moved onto an OSGi platform, but there’s still a lot of use for Spring along the way. Blueprint can help with the transition from Spring to OSGi. Where OSGi is likely to see a lot of growth is in the Platform-as-a-Service and cloud deployments; it’s possible to bootstrap a simple OSGi application to a replicated set of distributed services.
The source examples from the book are available here and this is a sample chapter.
About the Book Author
Dr Alex Blewitt works at an investment bank in London, but still finds the time to catch up with the latest OSGi and Eclipse news. Despite having previously been an editor for EclipseZone and a nominee for Eclipse Ambassador in 2007, his day-to-day role involves neither Eclipse nor Java. In what little time he has left over, he spends with his young family and has been known to take them flying if the weather's nice.