Accueil > Eclipse Extension Points > Eclipse Extension Points and Extensions without OSGi

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 :

  1. 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);
  2. 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 :

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.

Catégories :Eclipse Extension Points
  1. septembre 14, 2010 à 2:57

    Very cool. Thanks for this example!

    • septembre 14, 2010 à 3:00

      Many Thanks Lars for your comment and for your tutorial:)

  2. Ralf Zahn
    septembre 15, 2010 à 5:53

    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?

    • septembre 15, 2010 à 7:03

      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.

  3. Ralf Zahn
    septembre 15, 2010 à 7:50

    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…?

    • septembre 15, 2010 à 8:49

      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?

  4. Ralf Zahn
    septembre 15, 2010 à 10:25

    Yes, that sounds great!🙂

    • septembre 16, 2010 à 9:00

      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.

  5. Banderas
    octobre 12, 2010 à 2:54

    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?

    • octobre 12, 2010 à 3:04

      Hi Banderas,

      Sorry I don’t understand the link with this article? Which conflict do you mean?

      Regards Angelo

      • Banderas
        octobre 12, 2010 à 3:12

        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

  6. Banderas
    octobre 12, 2010 à 3:15

    There are 2 Project « myPanel » depends on « mainProject »

    • octobre 12, 2010 à 3:18

      Sorry I don’t understand. Are you in OSGi -env? Which is the link between Swing and Extension Point?

  7. Banderas
    octobre 12, 2010 à 3:22

    no problem thanks.

  8. juillet 19, 2013 à 2:53

    doesn’t work with eclipse 4.3 any more😦

    • juillet 20, 2013 à 11:08

      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.

      • juillet 30, 2013 à 3:46

        solved: problem was that org.eclipse.core.runtime.compatibility.registry_3.5.200.v20130514-1256 contains an unsigned runtime_registry_compatibility.jar

  9. septembre 6, 2013 à 3:22

    x545, could you explain me how you have fixed your problem with unsigned JAR please? Many thank’s!

  1. No trackbacks yet.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :