From NetBeans Modules to OSGi and Back!
The big blocker for some in relation to the NetBeans Platform is its lack of OSGi support. OSGi is used widely as the modular basis of applications, enabling incorporation of a large set of libraries created by developers all over the world. A simple requirement for application extensibility is that that extensibility be based on the most widely accepted standard. That being the case, the ability for the NetBeans Platform to make use of OSGi bundles is not only an indication of its having adopted the generally accepted standard but also an indication of the versatility of the NetBeans Platform, since backward compatibility is holy to the NetBeans engineers.
So, how can OSGi be supported by the NetBeans Platform while not undermining backward compatibility? By enabling the NetBeans modular architecture to understand OSGi, in such a way that both/either can be used within desktop applications. Why not simply use Eclipse RCP instead if OSGi is what you want? Because Swing, on top of which the NetBeans Platform is based, is the other generally accepted standard, while not being native to Eclipse RCP.
Hence, there is the Netigso build of the NetBeans IDE:
http://hudson.apidesign.org/job/netigso
It lets you combine NetBeans modules with OSGi bundles. (The name "Netigso" consists of "Net" from NetBeans, attached to "OSGi" spelled backwards.) For quite some time, that build has been broken. No more. It works now.
- Download the build above and then use it to create a new NetBeans module. In the manifest, change the "OpenIDE-Module" key to "Bundle-SymbolicName". Now, when you build the module, you will have an OSGi bundle because the NetBeans build system will create an OSGi bundle when the above key is set in the manifest.
- Let's now use some of the NetBeans API classes inside our OSGi bundle! Use the New Action wizard and then fill out the generated class like this:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
public final class SomeAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
NotifyDescriptor dd = new NotifyDescriptor.Message("Hello from " + getClass().getClassLoader());
DialogDisplayer.getDefault().notify(dd);
}
}The New Action wizard registers the above automatically in the layer.xml file. (Isn't it cool that you can use a standard ActionListener to define your actions, rather than one that is specific to the NetBeans APIs?) Note also that the above implies that your module has a dependency on the NetBeans Dialogs API.
- Now run the module. A new NetBeans Platform application will start up and your OSGi bundle will be installed into it. That means that the NetBeans Platform's runtime container understands OSGi because it treats the OSGi bundle just like any other NetBeans module. Then, when you invoke the action provided by the OSGi bundle, causing the dialog to appear, you will see that OSGi is able to interact with the NetBeans Platform, since it needs to do so to be able to call into the NetBeans module that provides the Dialogs API.
Hurray. Now you're able to create complex desktop applications on top of OSGi and Swing, in a completely natural way, using NetBeans IDE. The result could be a robust and pluggable application, such as any of these. Meanwhile, backward compatibility is assured since NetBeans modules can be used exactly as before.
- Login or register to post comments
- 1705 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)















Comments
Wayne Beaton replied on Wed, 2009/05/13 - 12:04pm
Geertjan Wielenga replied on Wed, 2009/05/13 - 12:07pm
Wayne Beaton replied on Wed, 2009/05/13 - 12:47pm
Cool. So... does it run on Equinox? That'd be something: NetBeans running on Eclipse...
FWIW, I mean this in a complementary sort of way, not in an either-is-subordinate-to-the-other sort of way.
Tom Wheeler replied on Wed, 2009/05/13 - 12:49pm
Although NetBeans module system supports a few features which OSGi does not (and vice versa), both module systems are probably 90% the same. I've always felt the module format is little more than an implementation detail, because in the course of developing a platform application, I spend very little time on code which has anything at all to do with the module system. Instead I spend most of my time working on application's business logic and user interface, so the ability to use Swing is much more important to me. It's important, of course, because it allows you to reuse existing code, locate third-party components and rely on the experience your developers already have.
Still, it is certainly nice that you can have your choice of module systems and still use Swing.
Wayne Beaton replied on Wed, 2009/05/13 - 2:47pm
FWIW, there's nothing stopping you from using Swing with Equinox and parts of the Eclipse platform.
The power provided by the module system becomes very important when your application gets relatively large and the complexity increases. Especially if you want it to be dynamically extensible. Being able to do things like have two versions of the same component running simultaneously can be very valuable (especially in a large system created by multiple teams).OSGi also provide useful things like a very powerful services implementation (along with declarative services) which is hard to live without once you've experienced it.
Tom Wheeler replied on Wed, 2009/05/13 - 4:28pm
Likewise, there's nothing preventing you from creating an application on the NetBeans Platform that uses a GUI toolkit other than Swing or creating an application which has no UI at all. But being able to reuse the visual components of the platform (like the window system, options window or explorer views) can save a great deal of time and let you concentrate on the business logic.
FWIW, the NetBeans Platform's module system also has a very powerful services mechanism which supports several types of declarative registration, plus deferred loading, content change listeners and many other features. As I said before, the two systems are mostly equivalent to one another, but since OSGi is a de facto standard, it's nice to have that choice now too.
Geertjan Wielenga replied on Wed, 2009/05/13 - 5:00pm
in response to: wayner42
That's a slightly odd paragraph since its content is equally applicable to the NetBeans Platform.
Neil Bartlett replied on Wed, 2009/05/13 - 5:10pm
This sounds great but it's drastically short on details of what you've actually done!
This sentence is curious: "The NetBeans Platform's runtime container understands OSGi because it treats the OSGi bundle just like any other NetBeans module". It sounds like you aren't actually using OSGi at all, just got the existing NetBeans module system to understand OSGi metadata and treat bundle JARs as NB modules. But then later you said you were using Felix. It's all a bit confusing!
Some concrete questions then:
Thanks!
Geertjan Wielenga replied on Wed, 2009/05/13 - 5:17pm
Thanks for the questions, Neil. Answers here: http://wiki.netbeans.org/OSGiAndNetBeans. Hopefully Jaroslav Tulach or others will stop by here to fill in other details to questions you've posed.
Jaroslav Tulach replied on Thu, 2009/05/14 - 2:20am
in response to: wayner42
It is probably possible to adjust the system to run on other OSGi container, but that is not high priority for me right now. We need better version mapping, support for simpler development, and many more urgent things.
As such using Equinox or Felix 1.6 is not a matter of replacing one JAR, but needs a little bit of coding.
Jaroslav Tulach replied on Thu, 2009/05/14 - 2:32am
in response to: neil.bartlett
Neil Bartlett replied on Thu, 2009/05/14 - 8:16am
in response to: jst
Thanks Jaroslav for the information.
So it appears you have two module systems running in parallel. This is very interesting because -- as I joked in my earlier message -- interoperability of module systems is a hard problem that various JSRs (including 277 and 294) have tried and failed to solve.
As I understand it, the NetBeans module system uses module-level dependencies, equivalent to OSGi's Require-Bundle, is that correct? Does that mean that dependencies between OSGi and NB modules must be done with Require-Bundle rather than the preferred Import-Package?
My question about OSGi services was specifically about OSGi services, not about ServiceLoader. Incidentally I think it's a stretch to call ServiceLoader "the standard" as it was only introduced as public API in Java 6. Anyhow, clearly if you have OSGi bundles using OSGi services they can talk to each other, and if you have NB modules using ServiceLoader they can talk to each other... but again, how do we cross the gap? Can I publish a service from an OSGi bundle and bind to it from a NB module, or vice versa?
Finally, do you see the current work as a transitional step on the way to full OSGi support, i.e. where OSGi is the only module system present in a NetBeans application?
Many thanks, Neil
Geertjan Wielenga replied on Thu, 2009/05/14 - 8:53am
I don't think that will ever be the case. It would mean that all NetBeans Platform modules would need to be OSGi bundles, making NetBeans Platform modules unusable for anyone who prefers the NetBeans module system. Wouldn't be very nice in terms of backward compatibility. This hybrid option, i.e., supporting both, giving developers the choice to choose either one, is great and -- at least in my opinion -- even preferable (and as Tom points out above, the whole question of the importance of this question is relative: "I've always felt the module format is little more than an implementation detail, because in the course of developing a platform application, I spend very little time on code which has anything at all to do with the module system. Instead I spend most of my time working on application's business logic and user interface, so the ability to use Swing is much more important to me.")
In other words, the question of using the standard UI toolkit (i.e., Swing) is typically of far greater significance to developers than whether they can use only OSGi or not.
Fabrizio Giudici replied on Thu, 2009/05/14 - 10:05am
For curious people:
1. First, Anton Epple (NBDT) will talk about NetBeans and OSGi at OSGi DevCon: http://www.osgi.org/DevConEurope2009/Speakers#Epple
2. Second, I could be able to demonstrate something at Community One http://developers.sun.com/events/communityone/2009/west/agenda.jsp, "NetBeans Platform (*) + Wicket = Reusable Components and Modular Web Apps [ESP 302]". I've used the conditional because the talk is about using the NetBeans Platform on the server side (everything is already working) and I'm right now working to try to OSGify it - among the commenters of this thread, I'm certainly the less experienced with OSGi.
(*) I've just seen that the title is wrong! Not NetBeans IDE, but NetBeans Platform!
Daoud AbdelMone... replied on Thu, 2009/05/14 - 5:20pm
Jaroslav Tulach replied on Fri, 2009/05/15 - 4:35am
in response to: neil.bartlett
However the Netigso bridge presents each NetBeans module as an OSGi bundle with some exported packages to the Felix runtime. As such OSGi bundles can use both Require-Bundle as well as Import-Package[1].
Thanks for this question. I guess this needs deeper toughts and a little bit of additional work. I can make services registered to BundleContext visible to NetBeans modules via Lookup. It might be useful.
The other direction - e.g. exposing content of
Lookup.getDefault()to BundleContext looks slightly artificial. At the end one always needs a dependency on the actual API class and then your are likely to have direct access toLookup.getDefault()or ServiceLoader[2] anyway.[1] Import-Package is understood in runtime. Naturally Felix knows how to handle it. On the other hand, the development support in NetBeans IDE generates only Require-Bundle dependencies right now.
[2] The ServiceLoader is just a gate to Java's Service Provider API which is in use since 1.3. True, the JDK class to access the registrations was not public, but that was also another reason why use the Lookup library.
Jaroslav Tulach replied on Fri, 2009/05/15 - 4:33am
in response to: Kmelleon
Geertjan Wielenga replied on Fri, 2009/05/15 - 4:39am
in response to: jst
Yes! That would be really great. I was experimenting yesterday to see if that was already happening, somehow, but it isn't. I'd like to do Lookup.getDefault().lookup(MyService.class), where 'MyService.class' is a service registered in the BundleContext of an OSGi bundle. That would make NetBeans modules truly interoperable with OSGi bundles!
Jaroslav Tulach replied on Fri, 2009/05/15 - 4:39am
in response to: fabriziogiudici
Neil Bartlett replied on Fri, 2009/05/15 - 1:46pm
in response to: geertjan
Well no, it wouldn't be truly interoperable until it works in both directions.
Jaroslav, the issue with ServiceLoader under OSGi of course is that the static method you put in the interface (yikes!) would not have visibility of any implementation classes if they appeared in different bundles. Of course you could ensure that implementations are always in the same bundle as their APIs, but that would hardly be good for modularity or extensibility.
One possible approach to integrating NB services in OSGi is to use an extender bundle to examine the contents of the META-INF/services files and publish the implementation objects listed there as services on behalf of the bundle that offers them. Of course this is quite limited because the metadata for ServiceLoader-style services contains only a classname, and says nothing about what other services are used by that service!
Because of this, I look at META-INF/services as an impoverished version of OSGi's Declarative Services. Still, if you have services that don't need to depend on other services this integration approach could work.
Fabrizio Giudici replied on Fri, 2009/05/15 - 2:45pm
Geertjan Wielenga replied on Sat, 2009/05/16 - 5:01am
in response to: fabriziogiudici