[RSS]


NetBeans and OSGi

NetBeans Module System and OSGi are kind of similar. They provide a way how to write modular systems, they encode their metadata in MANIFEST.MF, etc. This page has been create to host the "alignment" effort, e.g. ideas, plans and other work that could lead to crossing the gap and making the system even more similar, potentially replaceable. This would allow NetBeans to benefit from existing packaged modules available for example at SpringSource OSGI bundle repository which hosts binaries for popular open source projects.

All of this started when Richard S. Hall told me that he is a NetBeans IDE user, but the fact that NetBeans cannot run inside of Felix makes him look bad inside his own community. He said that he would like to try to port NetBeans and I thought, ok, that is not bad idea. If anyone wants to try it, we (I mean Sun employees working on NetBeans) are not going to stop you. In fact we are even able to give you some advices. This page contains the advices we gathered so far.

133-build-netigso-1.png

Resources

Runtime: Both NetBeans and Felix

The current prototype contains one additional module core.netigso which embeds Felix. This module hooks into the NetBeans module system and in case there is a module without standard OpenIDE-Module tag, but with Bundle-SymbolicName one, it takes care of it:

  • it starts the Felix runtime
  • it register the JAR in the Felix runtime
  • it creates a NetigsoModule wrapper around the bundle and registers it to NetBeans module system
This way any NetBeans module can have dependency on registered OSGi bundles. Also as soon as the Felix runtime is started, the system creates fake bundles for every NetBeans module. Due to this, it is possible for OSGi bundles to depend on any NetBeans module with public packages.

Tutorials

Metadata Mapping

There is an excellent 1:1 mapping provided by Richard Hall, yet it is bit too complex due to the attempt to support implementation dependencies. This is not really needed in the dual system which has both containers running in parallel. If one needs implementation dependency one can write NetBeans modules. If one wants OSGi, then one can depend just on public exported packages. As such the mapping is really simplified:

NetBeans OSGi Comment
OpenIDE-Module: org.mymodule Bundle-SymbolicName: org.mymodule
OpenIDE-Module-Specification-Version: 7.3 Bundle-Version: 7.3 for org.mymodule
OpenIDE-Module: org.mymodule/2 Bundle-SymbolicName: org.mymodule
OpenIDE-Module-Specification-Version: 7.3 Bundle-Version: 207.3 for org.mymodule/2
OpenIDE-Module-Public-Packages: x.y.z Export-Package: x.y.z
OpenIDE-Module-Module-Dependencies: another.module > 2.1 Require-Bundle: another.module;version="[2.1, 100.0)"
OpenIDE-Module-Module-Dependencies: another.module/2 > 2.1 Require-Bundle: another.module;version="[202.1, 300.0)"
OpenIDE-Module-Module-Dependencies: another.module/1-2 > 1.38 Require-Bundle: another.module;version="[101.38,300)"
OpenIDE-Module-Module-Dependencies: mysistermodule = 1.0-release-g not supported
OpenIDE-Module-Layer: Recognized

Development: Want an OSGi bundle or a NetBeans module?

The current apisupport harness has been extended to allow generation of both NetBeans as well as OSGi modules/bundles. Each project has its own manifest.mf file. In case there is OpenIDE-Module tag, the build injects NetBeans metadata into the final JAR's manifest. In case the previous tag is missing, and there is Bundle-SymbolicName tag, the OSGi like dependencies are injected instead. This allows people to easily switch between both systems with just a single line change in the manifest.mf file. Most of the changed code is in JarWithModuleAttributes Ant task.

Status & ToDo list

  • Bugs
  • NB67PerfPlan/yes.png How to adopt Library Wrappers to support OSGi JARs? Probably we do not need wrapper JARs anymore. How the build shall be changed?
 ant -f $NETIGSO/harness/suite.xml clusterize -Dcluster=`pwd` -Dincludes=modules/**
    • Clusterize works partially. After clusterizing:
      • NB67PerfPlan/yes.png I can import the cluster, See the module, Set a dependency on it from another module
      • but: it's not listed in the loaded modules and the BundleActivator isn't called - result of all modules being autoloads by default. Needs dedicated UI.
  • UI for clusterizing set of bundles (Toni):
  • Map localizing attributes (name, displayname, etc.) - straightforward
  • NB67PerfPlan/yes.png Try to support OpenIDE-Module-Layer in bundles
  • Extend Felix to eliminate current use of reflection
  • NB67PerfPlan/yes.png Lookup.getDefault() exposes what is registered via BundleContext.registerService(...)
  • BundleActivator.stop is never called
  • Expose BundleContext to Lookup.getDefault() (P3)
  • Proper version match
    • NetigsoModule.getCodeNameRelease is probably wrong, assuming we treat NB foo.bar/2 17.1.0 as OSGI foo.bar 2.17.1.0 as I recommend.
18:52:53 [----] GlickJesse:
findMethod should probably say: if (first == null) first = e;

18:55:49 [----] GlickJesse:
Can use NbCollections.checkedEnumerationByFilter in NetigsoLoader.

Rejected ideas

These ideas are currently unimplemented.

Can NetBeans run inside OSGi container?

Can Felix recognize modules in the current NetBeans locations. E.g. platformX/modules/ or ideY/modules, etc. If that would be doable, then good, we do not need to do any changes to the layout.

It depends on what you mean to "recognize" them, but if I understand what you mean, then I think we have a couple of options:

  • We could create a sort of "launcher" bundle that probes the local machine (or user home) for installed NetBeans systems and could then launch a discovered installation by automatically installing the modules discovered in the locations you mention.
  • Or we could create a custom launcher for Felix that can discover a NetBeans installation and then automatically load the modules from the above locations into the OSGi framework.

Last thing related to this is classpath. Currently NetBeans contain three JARs that are on classpath (platform/lib/*.jar) and two that are treated in a special way (platform/core/*.jar). I guess that in your proposal, you would like to treat these as modules. Felix would be on classpath, all NetBeans JARs would be loaded dynamically completely under control of Felix.

It is not 100% necessary to have everything in a module, but that is probably better. The OSGi framework allows you to put stuff on the class path too. There are two ways for modules to access classes on the class path:

  • The class path packages can be exported by the OSGi framework, in which case modules that use them must explicitly import the corresponding packages.
  • The class path packages can also be made available to all modules implicitly (i.e., they don't have to import the associated packages), by a mechanism we call boot class path delegation.

So, it is probably better if everything is in a module, but it is not strictly required. Ok, let's try to make everything a module/bundle.

Implementation dependencies

Can OSGi mimic implementation dependencies? E.g. bundle dependency when the other bundle sees even non-exported packages from the other one? Richard Hall shows in OSGiAndNetBeansMetadataMapping that this is possible, yet tricky and not in the spirit of NetBeans modularity (as it makes all module packages public to support implementation dependency) (Richard Hall says: I think it is the same spirit, they are only "publicly" available if you specify the proper metadata to access them, which is equivalent to specifying the proper metadata for an implementation dependency. If you allow implementation dependencies, you should just accept that your packages are in effect public, because you will break all clients of those packages if you refactor the packages. The only difference is clients should be aware that implementation packages might break more regularly.)

What NetBeans need to know about its modules:

  • Access to all resources of a module.
    • Achievable using Bundle entry-related methods (e.g., getEntry(), getEntryPaths(), and findEntry()).
  • Ability to have a "super" class loader that can load classes from all modules.
    • Achievable with a custom class loader that wraps all available bundles and calls Bundle.loadClass() to delegate to the bundles.
  • Generic provide/require tokens.
    • Achievable by exposing generic provide/require mechanisms of Felix and/or Equinox, but this would not be part of the OSGi R4.1 spec, but could be raised as an issue for R5 since it was discussed for R4.

Attachments