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.

  1. 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.

  2. 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.

  3. 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. 

 

0
Average: 5 (1 vote)

(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

So... is it just NetBeans pretending to be OSGi? Or is there actually an OSGi implementation under it? Does it actually provide the same functionality as OSGi?

Geertjan Wielenga replied on Wed, 2009/05/13 - 12:07pm

OSGi is many things, depending on the implementation. In this case, it is Felix.

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

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.

 

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:

  1. Are you actually running an OSGi framework?
  2. If so which one, and are you portable to the others?
  3. Are you embedding OSGi inside NetBeans, or is it OSGi "all the way down"?
  4. Are all NetBeans modules now OSGi bundles? If not then how do you define dependencies between NB modules and OSGi bundles such that the two module systems can interoperate? If you have solved this problem then I think the JSR 294 expert group would like to hear from you urgently!
  5. Do you use OSGi services for inter-bundle glue? If not, then what?

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

Currently the Netigso build runs on Felix 1.4.* versions only as it calls into implementation classes of the Felix runtime.

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

 

>Are you embedding OSGi inside NetBeans, or is it OSGi "all the way down"?

The system is capable of running both NetBeans Runtime Container and Felix in parallel. The modules in the first and the bundles in the latter can moreover declare mutual inter-dependencies and call to each other.

> Do you use OSGi services for inter-bundle glue? If not, then what?

Certainly bundles can use the standard Java service provider mechanism for component injection as is common in NetBeans. There is also no reason why bundles shall be prevented to communicate with themselves using standard OSGi techniques.

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

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?

 

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

Am not really very knowledgeable about OSGi. Far from what I've seen I miss some feature present in the NB platform: the ability to package a bunch of plugins in a single suite to provide a functionality out from those separate modules let say (API/implementation/model/UI).

Jaroslav Tulach replied on Fri, 2009/05/15 - 4:35am in response to: neil.bartlett

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?
Yes and no. Yes, NetBeans module system only uses module dependencies. As such a NetBeans module can only specify module dependency on OSGi bundle - e.g. require that bundle.

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].

Can I publish a service from an OSGi bundle and bind to it from a NB module, or vice versa?

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 to Lookup.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

Hello Kmelleon. Your request is really Netigso unrelated, but you might be pleased with suite chaining.

Geertjan Wielenga replied on Fri, 2009/05/15 - 4:39am in response to: jst

I can make services registered to BundleContext visible to NetBeans modules via Lookup. It might be useful.

 

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

Go on Fabrizio! NetBeans and/or Netigso deserves more publicity among the OSGi crowd.

Neil Bartlett replied on Fri, 2009/05/15 - 1:46pm in response to: geertjan

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!

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

I think that many of us, in order to fully understand things as those mentioned in the last comment, need some example...

Geertjan Wielenga replied on Sat, 2009/05/16 - 5:01am in response to: fabriziogiudici

Agreed! The real benefit of OSGi integration with the NetBeans runtime container will come when the OSGi BundleContext's services are made available to the NetBeans Lookup. That, in fact, practically speaking (as opposed to theoretically/academically) is all that's really missing at this point. Then the whole world of OSGi will be open to NetBeans Platform developers! How cool that will be.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.