Eclipse Extension Points and Extensions without OSGi
Eclipse provides the concept of « extension points » and « extensions » to facilitate that functionality can be contributed to plugins by other plugins.. Lars Vogel explained very good this mechanism in her Eclipse Extension Points and Extensions – Tutorial.
In this tutorial, you can find 2 Plug-ins :
- de.vogella.extensionpoint.definition Plug-in (Eclipse RCP) which :
- defines the Extension Point de.vogella.extensionpoint.definition.greeter declared in the plugin.xml :
<plugin> <extension-point id="de.vogella.extensionpoint.greeters" name="Greeters" schema="schema/de.vogella.extensionpoint.greeters.exsd"/> </plugin>
to get instance of de.vogella.extensionpoint.definition.IGreeter.
- reading the registered extension (registered by the second Plug-in de.vogella.extensionpoint.contribution) to retrieve de.vogella.extensionpoint.definition.IGreeter instance :
IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(IGREETER_ID);
- defines the Extension Point de.vogella.extensionpoint.definition.greeter declared in the plugin.xml :
- de.vogella.extensionpoint.contribution which provides the Extension to register an instance of de.vogella.extensionpoint.contribution.GreeterGerman declared in the plugin.xml :
<plugin> <extension point="de.vogella.extensionpoint.definition.greeter"> <client class="de.vogella.extensionpoint.contribution.GreeterGerman"> </client> </extension> </plugin>
This sample works well in OSGi context, but is it possible to use Extension Point/Extension mechanism without OSGi? The answer is yes! The Plug-in org.eclipse.equinox.registry which manages the Extension Point/Extension mechanism works only with OSGi context, but the Extension Point/Extension API was thought to be extensible and not linked to OSGi.
The bug 322189 provides the Plug-in org.eclipse.equinox.nonosgi.registry which implements Extension Point without OSGi (but with OSGi too). In this article I will explain how use org.eclipse.equinox.nonosgi.registry by modifying (a little) the Lars tutorial to launch de.vogella.extensionpoint.definition.Application with Java main (without OSGi context) :
public static void main(String[] args) { IApplication application = new Application(); try { application.start(null); } catch (Exception e) { e.printStackTrace(); } }
Why using Extension Point without OSGi?
I have decided to implement « Eclipse Extension Points and Extensions without OSGi » that you can find in the bug 322189, because the Eclipse E4/CSS Engine is configured with Extension Point and works (today) only in OSGi context. Sometimes you have not the luck to use OSGi and it can be interesting to provides the capability to manage Extension Point in OSGi context AND without OSGi. CSS Engine which is enable to configure SWT Widgets with CSS styles is good sample. You can use SWT without OSGi, so why you could not use Eclipse E4/CSS Engine without OSGi?
Lars projects
You can download Lars project in the extensionpoint_nonosgi_step1.zip and import it in your workspace. This zip contains :
- the de.vogella.extensionpoint.definition Plug-in (Eclipse RCP).
- the de.vogella.extensionpoint.contribution Plug-in.
- launch project which contains the OSGi Eclipse Application launch de.vogella.extensionpoint.definition.application.launch explained in the Lars Tutorial.
Once you have imported those 3 project, Run launch de.vogella.extensionpoint.definition.application.launch with Run As->de.vogella.extensionpoint.definition.application :
the console display :
Starting
Evaluating extension
Moin Jungs!
which means that Extension coming from de.vogella.extensionpoint.contribution is well registered.
The Problem without OSGi
To see the problem with Extension without OSGi, add the Java Main method in the de.vogella.extensionpoint.definition.Application like this :
public static void main(String[] args) { IApplication application = new Application(); try { application.start(null); } catch (Exception e) { e.printStackTrace(); } }
Launch this Java Main with Run As/Java Application :
The console display a NullPointerException error :
java.lang.NullPointerException
at de.vogella.extensionpoint.definition.Application.runGreeterExtension(Application.java:42)
at de.vogella.extensionpoint.definition.Application.start(Application.java:21)
at de.vogella.extensionpoint.definition.Application.main(Application.java:34)
This error comes from with the code :
IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(IGREETER_ID);
where Platform.getExtensionRegistry() is null because we are not in OSGi context.
org.eclipse.equinox.nonosgi.registry
You can download extensionpointnonosgi_step2.zip which contains projects explained in this section.
The bug 322189 provides the project org.eclipse.equinox.nonosgi.registry which manages Extension Point without OSGi (but with OSGi too). In this bug you will find the org.eclipse.equinox.nonosgi.registry_100816.zip where there are samples with Eclipse E4/CSS Engine (with and without OSGi), documentation about the samples and the project org.eclipse.equinox.nonosgi.registry. Download this zip and import the org.eclipse.equinox.nonosgi.registry in your workspace.
Your workspace looks like this :
RegistryFactoryHelper
The org.eclipse.equinox.nonosgi.registry provides an helper org.eclipse.equinox.nonosgi.registry.RegistryFactoryHelper which returns the IExtensionRegistry instance switch the context (OSGi-env, NO OSGI-env). So instead writing this :
IExtensionRegistry registry = Platform().getExtensionRegistry();
which manage ONLY OSGi-env, you can use org.eclipse.equinox.nonosgi.registry..RegistryFactoryHelper like this :
IExtensionRegistry registry = RegistryFactoryHelper.getRegistry();
This code manage the two context (« with OSGi » and « without OSGi »). In NO OSGi context, this helper will load the whole plugin.xml founded from the classpath. It’s very important to understand that : plugin.xml (and MANIFEST.MF) must be included to the classpath!
RegistryFactoryHelper – de.vogella.extensionpoint.definition
Here we modify the de.vogella.extensionpoint.definition project to use RegistryFactoryHelper like this :
- Add Required-Bundles org.eclipse.equinox.nonosgi.registry in the MANIFEST.MF to use RegistryFactoryHelper :
- use RegistryFactoryHelper in the Application to get the IExtensionRegistry like this :
//IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(IGREETER_ID); IConfigurationElement[] config = RegistryFactoryHelper.getRegistry().getConfigurationElementsFor(IGREETER_ID);
Relaunch this Java Main with Run As/Java Application, the console display (not a NullPointerException error) but just :
starting
At this step NullPointerException is avoided but NO Extension is registered.
debug mode
It’s possible to trace which plugin.xml are loaded. To debug that you can add the JVM Parameter org.eclipse.equinox.nonosgi.registry.debug like this :
-Dorg.eclipse.equinox.nonosgi.registry.debug=true
Go to the Application launch configuration to add this JVM Parameters :
Relaunch it. You will see on console some traces :
[org.eclipse.equinox.nonosgi.registry] BEGIN RegistryStrategyNonOSGI#onStart
[org.eclipse.equinox.nonosgi.registry] Start searching URLs from the ClassLoader....
[org.eclipse.equinox.nonosgi.registry] End searching URLs from the ClassLoader with time=0(ms)
[org.eclipse.equinox.nonosgi.registry] Start searching URLs from the ClassLoader....
[org.eclipse.equinox.nonosgi.registry] End searching URLs from the ClassLoader with time=0(ms)
[org.eclipse.equinox.nonosgi.registry] Start loading ....
[org.eclipse.equinox.nonosgi.registry] [OK] loaded with time=78(ms) : (file:/D:/eclipses/eclipse-jee-helios-win32/eclipse/plugins/org.eclipse.core.runtime_3.6.0.v20100505.jar!/plugin.xml)
[org.eclipse.equinox.nonosgi.registry] [OK] loaded with time=0(ms) : (file:/D:/eclipses/eclipse-jee-helios-win32/eclipse/plugins/org.eclipse.equinox.registry_3.5.0.v20100503.jar!/plugin.xml)
[org.eclipse.equinox.nonosgi.registry] [OK] loaded with time=0(ms) : (file:/D:/eclipses/eclipse-jee-helios-win32/eclipse/plugins/org.eclipse.equinox.preferences_3.3.0.v20100503.jar!/plugin.xml)
[org.eclipse.equinox.nonosgi.registry] [OK] loaded with time=16(ms) : (file:/D:/eclipses/eclipse-jee-helios-win32/eclipse/plugins/org.eclipse.core.contenttype_3.4.100.v20100505-1235.jar!/plugin.xml)
[org.eclipse.equinox.nonosgi.registry] [OK] loaded with time=0(ms) : (file:/D:/eclipses/eclipse-jee-helios-win32/eclipse/plugins/org.eclipse.equinox.app_1.3.0.v20100512.jar!/plugin.xml)
[org.eclipse.equinox.nonosgi.registry] End loading with time=94(ms)
[org.eclipse.equinox.nonosgi.registry] END RegistryStrategyNonOSGI#onStart: plugin.xml [OK]=<5/5>, plugin.xml [ERROR]=<0/5>, time=125(ms).
[org.eclipse.equinox.nonosgi.registry] Returns IExtensionRegistry from the NO OSGi-env. Thread=Thread[main,5,main]
This trace is helpful because it show you which plugin.xml are loaded. The trace :
[org.eclipse.equinox.nonosgi.registry] END RegistryStrategyNonOSGI#onStart: plugin.xml [OK]=<5/5>, plugin.xml [ERROR]=<0/5>, time=125(ms).
show you that there is 5 plugin.xml which was loaded. Those plugin.xml comes from the Eclipse Home. For instance the trace :
[OK] loaded with time=78(ms) : (file:/D:/eclipses/eclipse-jee-helios-win32/eclipse/plugins/org.eclipse.core.runtime_3.6.0.v20100505.jar!/plugin.xml)
means that plugin.xml coming from the org.eclipse.core.runtime_3.6.0.v20100505.jar coming from the Eclipse home was loaded.
plugin.xml in the classpath
At this step 5 plugin.xml are loaded. They come from the Eclipse Home. But why plugin.xml coming from de.vogella.extensionpoint.definition and de.vogella.extensionpoint.contribution are not loaded? The answer is classpath. Indeed org.eclipse.equinox.nonosgi.registry works only if plugin.xml is in the classpath (and MANIFEST.MF too). When we will build JAR of de.vogella.extensionpoint.definition and de.vogella.extensionpoint.contribution, you will not have this problem.
To fix the problem you must modify classpath to add the 2 plugin.xml (and the 2 MANIFEST.MF) coming from de.vogella.extensionpoint.definition and de.vogella.extensionpoint.contribution on other words, you must add this 2 folders in the classpath. To do that, edit the Run->Configuration Application and go at Classpath tab :
Click on Advanced.. button to open Advanced Options and select Add Folders option :
Select the 2 de.vogella.extensionpoint* projects :
Click on OK button, the 2 folders which contains plugin.xml and MANIFEST.MF are added :
Relaunch the Java Main Application and you will see on the console :
...
[org.eclipse.equinox.nonosgi.registry] [OK] loaded with time=0(ms) : (/D:/_Projets/Personal/workspace-extensionpoint-wordpress/step2-0/de.vogella.extensionpoint.contribution/plugin.xml)
[org.eclipse.equinox.nonosgi.registry] [OK] loaded with time=0(ms) : (/D:/_Projets/Personal/workspace-extensionpoint-wordpress/step2-0/de.vogella.extensionpoint.definition/plugin.xml)
[org.eclipse.equinox.nonosgi.registry] End loading with time=94(ms)
[org.eclipse.equinox.nonosgi.registry] END RegistryStrategyNonOSGI#onStart: plugin.xml [OK]=<7/7>, plugin.xml [ERROR]=<0/7>, time=125(ms).
You can notice that our plugin.xml are loaded, but you have the trace :
Evaluating extension
Contributor "de.vogella.extensionpoint.contribution" was unable to find class "de.vogella.extensionpoint.contribution.GreeterGerman".
which means that de.vogella.extensionpoint.contribution.GreeterGerman can be not founded. Indeed this class is not in the classpath.
Class in the classpath
To fix classpath problem we must add the de.vogella.extensionpoint.contribution project in the classpath. To do that edit the Application launch and click on Add Projects button :
Select the de.vogella.extensionpoint.contribution project :
Relaunch it and you will see in the console :
Starting
Evaluating extension
Moin Jungs!
which means that Extension coming from de.vogella.extensionpoint.contribution is well registered in NO OSGi context.
Build JAR
You can download extensionpointnonosgi_step3.zip which contains the projects explained in this section.
Here we will create a Java Project de.vogella.extensionpointnonosgi which will use the Plugin-in JAR built :
Here we will not have classpath problems because plugin.xml and MANIFEST.MF will be stored in the built JAR.
de.vogella.extensionpointnonosgi – Java Project
Create (a classic) de.vogella.extensionpointnonosgi Java Project.
Built Plug-In
Here we will create 3 JAR with the 3 projects de.vogella.extensionpoint.definition, de.vogella.extensionpoint.contribution and org.eclipse.equinox.nonosgi.registry projects. To do that, we will create the JAR with Eclipse (PDE tools). Go at the menu File/Export…. The Export wizard opens. Select Plug-in Development/Deployable plug-ins and fragment node :
Select the 3 bundles from the workspace and select directory WORKSPACE_LOC/de.vogella.extensionpointnonosgi where WORKSPACE_LOC is your workspace directory. You will notice that it’s NOT WORKSPACE_LOC/de.vogella.extensionpointnonosgi/plugins (with /plugins folder) which is selected, because PDE Tools generate this folder.
Click on Finish button, refresh the de.vogella.extensionpointnonosgi the Java Project, and /plugins folder must appear with 3 JARs :
Other JAR
Copy the following JAR that you can find in your ECLIPSE_HOME/plugins folder :
- org.eclipse.core.runtime_3.6.0.v20100505.jar
- org.eclipse.equinox.app_1.3.0.v20100512.jar
- org.eclipse.equinox.common_3.6.0.v20100503.jar
- org.eclipse.equinox.registry_3.5.0.v20100503.jar
- org.eclipse.osgi_3.6.0.v20100517.jar
Add the whole JAR from the /plugins folder in the classpath with Add JARs… button :
MainApplication
Create de.vogella.extensionpointnonosgi.MainApplication class like this :
package de.vogella.extensionpointnonosgi; import org.eclipse.equinox.app.IApplication; import de.vogella.extensionpoint.definition.Application; public class MainApplication { public static void main(String[] args) { IApplication application = new Application(); try { application.start(null); } catch (Exception e) { e.printStackTrace(); } } }
Run this class. You will see in the console :
Starting
Evaluating extension
Moin Jungs!
which means that Extension coming from de.vogella.extensionpoint.contribution is well registered.
debug mode
We have seen debug mode is activated with JVM Parameter org.eclipse.equinox.nonosgi.registry.debug, but it’s possible to activate it with the nonosgiregistry.properties properties file. To do that, create the file nonosgiregistry.properties in the /src folder like this
org.eclipse.equinox.nonosgi.registry.debug = true
If you relaunch MainApplication launch, you will see trace which display which plugin.xml are loaded.
Single-Sourcing : I don’t want use RegistryFactoryHelper.getRegistry() in my Plug-In
When you wish develop Plug-In to use it in OSGi and without OSGi we have seen that :
- Your Plug-In must depends on org.eclipse.equinox.nonosgi.registry with Required-Bundles.
- Your Plug-In must use RegistryFactoryHelper.getRegistry() instead of using Platform.getExtensionRegistry()
This dependence is annoying when you wish use existing Plug-In (which works in OSGi context) which use Platform.getExtensionRegistry() : you must modify your whole Plug-Ins to manage No OSGi context. Don’t think that! You can use Platform.getExtensionRegistry() in your Plug-In to manage NO OSGi context. The only thing to do in NO OSGi context is to initialize (at your bootstrap Application) the Extension Registry by calling RegistryFactoryHelper.getRegistry().
So in NO OSGi context, you can do :
- call at your bootstrap Application (ex : your Java Main Application) RegistryFactoryHelper.getRegistry().
- Use Platform.getExtensionRegistry() in your whole Plug-In.
You can download extensionpointnonosgi_step4.zip which show you that :
- The de.vogella.extensionpoint.definition Plug-In is not linked to the org.eclipse.equinox.nonosgi.registry and it use Platform.getExtensionRegistry() instead of using RegistryFactoryHelper.getRegistry() :
IConfigurationElement[] config = Platform.getExtensionRegistry().getConfigurationElementsFor(IGREETER_ID); //IConfigurationElement[] config = RegistryFactoryHelper.getRegistry().getConfigurationElementsFor(IGREETER_ID);
- MainApplication is modified like this :
package de.vogella.extensionpointnonosgi; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.nonosgi.registry.RegistryFactoryHelper; import de.vogella.extensionpoint.definition.Application; public class MainApplication { public static void main(String[] args) { // 1) Force plugin.xml loading. RegistryFactoryHelper.getRegistry(); // 2) Use Platform.getExtensionRegistry() on the whole plugins instead // of using RegistryFactoryHelper.getRegistry() IApplication application = new Application(); try { application.start(null); } catch (Exception e) { e.printStackTrace(); } } }
Conclusion
In this article I have explained how use org.eclipse.equinox.nonosgi.registry to manage Eclipse Extension Points and Extensions without OSGi (and with OSGi too). The sample used in this article is very simply, but it’s important to think that plugin.xml are loaded at the first call of the RegistryFactoryHelper. I have not tested org.eclipse.equinox.nonosgi.registry with a lot of plugin.xml files and I don’t if with a lot of plugin.xml the loading can be slow?
org.eclipse.equinox.nonosgi.registry give you the capability to use the power of the Eclipse Extension Points and Extensions in your API (like we could use it in the Eclipse E4/CSS Engine) which can work with OSGi and without OSGi.
Very cool. Thanks for this example!
Many Thanks Lars for your comment and for your tutorial:)
Nice to know about this possibility. Thanks!
Is there any single source solution that we can exchange the OSGi plugin by the non-OSGi plugin to get all plugins work that are not dependent from the OSGi platform?
Hi Ralf,
I’m happy that this article please you. I’m sorry but I don’t understand your question. Could you please give me some more information/sample.
Thanks.
In your article, I see that my plugin needs a dependency to org.eclipse.equinox.nonosgi.registry to use a RegistryFactoryHelper class.
Single sourcing would mean that I do not need any further dependency and do not need any further helper class, I just could simply use Platform.getExtensionRegistry().
Maybe this is not possible with the current Eclipse API, but I’d like to discuss. You have a single-sourcing variant because the RegistryFactoryHelper class can be used within both OSGi- and non-OSGi-context. But this is only usable for my own plug-ins, not for third-party plug-ins or even common Eclipse plug-ins.
Maybe Eclipse 4.0 with DI could solve that problem…?
Thank’s Ralf for your explanation. I understand what you mean. Problem comes from with static method which call Platform.getExtensionRegistry(), which call RegistryFactory.getRegistry() which is initialized by default with OSGi and returns null if there are no OSGi initialisation and an instance of IExtensionRegistry in the OSGi case. RegistryFactoryHelper is just an helper which call RegistryFactory.getRegistry() and test if the instance returned is null. If IExtensionRegistry returned is not null we are in OSGi context, if IExtensionRegistry is null I configure IExtensionRegistry like this RegistryFactory.setDefaultRegistryProvider(new RegistryProviderNonOSGI());
But after you can call Platform.getExtensionRegistry() on your another Plug-in if you wish. Your comment is very interesting. Problem comes from just with bootstrap to initialize IExtensionRegistry. So I suggest to do :
1. Use Platform.getExtensionRegistry() in your Plug-in.
2. In NON OSGi context call in your bootstrap Application (ex: at first line of your Java Main) RegistryFactoryHelper.getRegistry() to initialize IExtensionRegistry in NON OSGi-context.
What do you think about that?
Yes, that sounds great! 🙂
Hi Ralf,
I have added « Single-Sourcing : I don’t want use RegistryFactoryHelper.getExtensionRegistry() in my Plug-In » section at the end of this article with the sample modified to use Platform.getRegistry() in the Plug-In.
Thank’s a lot for your comment.
Hi Angelo,
I have a question, I want to add a Panel(myPanel) in a programm (mainProject), in this panel there are other components , but the problem is, that there are 2 Projects (1. mainProject, 2. myPanel ), « myPanel » works with swingx 1.6 and the project « mainProject » works with swingx 0.6., at the moment I have conflicts with the plugins. do you think, that I can use your solution for my problem?
Hi Banderas,
Sorry I don’t understand the link with this article? Which conflict do you mean?
Regards Angelo
Workspace – Eclipse:
mainProject (plugin 0.6) -> Project
myPanel (plugin 1.6) ->Project
I have problem with plugins, because when I start « mainProject », mainProjekt works only with swingx 0.6, « myPanel » works no more with swingx 1.6 although in « myPanel » there is the swingx 1.6
There are 2 Project « myPanel » depends on « mainProject »
Sorry I don’t understand. Are you in OSGi -env? Which is the link between Swing and Extension Point?
no problem thanks.
doesn’t work with eclipse 4.3 any more 😦
Never tested with 4.x. Could you tell me what is your problem? I wil try to try it when I will I have time.
solved: problem was that org.eclipse.core.runtime.compatibility.registry_3.5.200.v20130514-1256 contains an unsigned runtime_registry_compatibility.jar
x545, could you explain me how you have fixed your problem with unsigned JAR please? Many thank’s!
I Angelo,
I don’t understand why bug 322189 has been marked as wontfix. I would like to use your plugin, but did not find an update-site providing it. It would be great if you had some plans to make the nonosgi registry available somewhere…! In other cases, how should I use it (or not 😉 ?
> I don’t understand why bug 322189 has been marked as wontfix.
I don’t know.
> In other cases, how should I use it
It should work. What is your problem?
I Angelo,
Thank your for your quick reply.
The nonosgi registry works perfectly ! 😉
Sorry, my question was not clear. I was wondering about licensing and source hosting issues. I need to use the nonosgi registry for commercial and open source projects. As far as I understand, sources are not hosted publicly somewhere, nor an update-site is available, or a maven repository. Should I simply duplicate your sources and deploy the nonosgi plugin as part of my projects and their update-sites ? Should I copy a license text somewhere or ask an authorization from yourself ?
Kind regards
Romain
> I should perhaps creating a github project and clarify the license (use EPL).
It would be very nice…
> But you can use it, no problem.
Thanks a lot !
Indeed the license is not clear. The code is written by me and you can use it. I should perhaps creating a github project and clarify the license (use EPL). But you can use it, no problem.