Accueil > Equinox ServletBridge > OSGi Equinox in a Servlet Container [step6]

OSGi Equinox in a Servlet Container [step6]


In [step5], I have modified bridge WEB Application to use it as Electronic Document Management WEB Application.

A servlet CollectionsServlet defined in bridge WEB Application, display list of ICollection by using CollectionsRegistry singleton.

This singleton is used too in OSGi context by sample.collection1 bundle which register/unregister an instance of ICollection. CollectionsRegistry singleton comes from sample.collections.api JAR stored in /WEB-INF/lib (Tomcat System) and sample.collection1 use CollectionsRegistry (import package sample.collections.api ) singleton too.

In this article I will explain how CollectionsRegistry singleton can be shared between WEB Application context (CollectionsServlet) and OSGi context (sample.collection1 bundle) :

My first (bad) idea

At first sample.collections.api.jar which is used by CollectionsServlet must belong to the WEB-INF/lib (or WEB-INF/classes) because CollectionsServlet use the CollectionsRegistry singleton.

OSGi bundle sample.collection1 import the sample.collections.api package. How manage that? My first (bad) idea was to copy/paste /WEB-INF/lib/sample.collections.api.jar to the /WEB-INF/eclipse/plugins folder :

This solution doesn’t work but I think it’s interesting to see the problem. To do that, modify config.ini to add sample.collections.api as a bundle OSGi:

,${workspace_loc}/sample.collections.api

Restart your server (/sp_redeploy + restart server) and type in the console View

ss

The OSGi console display the Short Status of the bundles installed :

...
7 ACTIVE sample.collection1_1.0.0.qualifier
8 RESOLVED sample.collections.api_1.0.0.qualifier

sample.collection1 is ACTIVE. You will see too in the console the trace :

Register collection ID=1, label=Collection 1

which means sample.collection1 has registered an instance of ICollection in the CollectionsRegistry. Go at http://localhost:8080/bridge/collections URL to see the registered collections BUT??? :

The collection doesn’t appear?

Why?

The explanation with this problem is that CollectionsRegistry is instanciated twice (by CollectionsServlet, and by Activator of sample.collection1) although it’s static field? To see the problem in action, modify the CollectionsRegistry constructor with trace :

public CollectionsRegistry() {
	System.out.println("CollectionsRegistry=" + this);
}

Restart the server, you will see on the console :

CollectionsRegistry=sample.collections.api.CollectionsRegistry@1fbfd6

This trace comes from the sample.collection1 which use CollectionsRegistry to register the collection.

Go at http://localhost:8080/bridge/collections , you will see in the console a second trace :

CollectionsRegistry=sample.collections.api.CollectionsRegistry@8c4a77

This trace comes from CollectionsServlet which use CollectionsRegistry to get the registered collections. This second trace show you CollectionsRegistry is instantiated a second time. So it’s bad idea to set the sample.api.collections.jar in the OSGi Equinox container (/plugins). To follow next section, please remove

,${workspace_loc}/sample.collections.api

from the config.ini (and do a /sp_redeploy).

OSGi Fragment framework

To resume the situation, we have :

  • sample.collections.api JAR in the /WEB-INF/lib folder (WEB Application context).
  • sample.collection1 JAR in the /WEB-INF/eclipse/plugins folder (OSGi context). This bundle depends on sample.collections.api with Import package.

How sample.collection1 bundle could use sample.collections.api JAR (which is in this case not a bundle)? The answer is :

Fragment-Host: system.bundle; extension:=framework

On other words with OSGi it’s possible to use Java classes provided by the Java Platform (in our case JAR from WEB Application) but not provided inside the framework (OSGi Equinox) by creating an OSGi fragment linked to the bundle named « system.bundle ». In this fragment you can export packages (coming from WEB Application) that you wish. In our case :

Export-Package: sample.collections.api

.

For more information I suggest you to read
OSGi Bundles require Classes from the Environment
. An OSGi fragment is a kind of OSGi bundle linked to a bundle. It is used to configure the linked bundle (ex : if you have a bundle « A » which waits log4j.properties,you can create an OSGi fragment linked to A to set the log4j.properties). In our case the fragment will configure the well export package.

To do that you have 2 choices :

Fragment sample.collections.extensionbundle

Here we will create an OSGi Fragment with PDE. You can download servletbridge_step6-collections.extensionbundle.zip witch contains projects explained in this section.

  • the OSGi Fragment sample.collections.extensionbundle project which is linked to « system.bundle » and wich export sample.collections.api package. This project must be closed in your workspace to avoid having compilation problems.
  • The sample.collections.extensionbundle_1.0.0.jar stored in the /plugins folder of the bridge WEB Application
  • the bridge.target Target Platform modified.

Create Fragment

Here we create the fragment sample.collections.extensionbundle with PDE (Plug-in Development Environment). To do that go at menu File/New/Other… and Plug-in Development/Fragment Project :

Click on Next button, and :

  • fill Project name field with sample.collections.extensionbundle.
  • select the radio button an OSGI framework because we wish develop an OSGi fragment and select the combo standard.

Click on Next button, the wizard page which configure the OSGi fragment is displayed :

This fragment must be linked to the Bundle with ID « system.bundle », but PDE cannot find it (Why?). Choose any bundle (in my case I have choose sample.http) to finish the wizard. Open the META-INF/MANIFEST.MF file and go at MANIFEST.MF tab to modify it at hand with this content :

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Sample Collections Extension Bundle
Bundle-SymbolicName: sample.collections.extensionbundle
Bundle-Version: 1.0.0
Fragment-Host: system.bundle; extension:=framework
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Export-Package: sample.collections.api

  • the fragment is linked to « system.bundle » bundle (see Fragment-Host).
  • the fragment export the package sample.collections.api.

You will have some errors compilation in your workspace :

The problem is cause by our Fragment which try to search packages sample.collections.api in system library.

Create and deploy

To resolve the compilation problem :

Target Platform

The bridge.target Target Platform must be update because by default the fragment sample.collections.extensionbundle is selected and it will cause compilation problem if you activate the Target Platform (with « Set As Target Platform » link) :

Now you can test it.

Fragment org.eclipse.equinox.servletbridge.extensionbundle

If you see the Tomcat work folder, you will noticethat /plugins folder exists. It was created after /sp_redeploy.

If you see (YOUR_WORKSPACE/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/work/Catalina/localhost/bridge/eclipse/plugins), you will notice that it exists the JAR org.eclipse.equinox.servletbridge.extensionbundle_1.2.0.jar although this JAR doesn’t exist in your bridge WTP Dynamic Project? This JAR is generated when you do /sp_redeploy. If you unzip it and see the MANIFEST.MF you will see :

Manifest-Version: 1.0
Export-Package: org.eclipse.equinox.servletbridge; version=1.1, javax.
 servlet; version=2.5, javax.servlet.http; version=2.5, javax.servlet.
 resources; version=2.5
Fragment-Host: system.bundle; extension:=framework
Bundle-Version: 1.2.0
Bundle-Name: Servletbridge Extension Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.equinox.servletbridge.extensionbundle

You can notice :

  • it’s an OSGi fragment linked to « system.bundle » (Fragment-Host: system.bundle; extension:=framework).
  • it’s export some packages like javax.servlet.http and org.eclipse.equinox.servletbridge.

This fragment manage the capability to import javax.servlet.http packages in custom bundles although javax.servlet.http bundle is not present in the /plugins folder. As this fragment is generated, « OSGi Equinox in a Servlet Container » give you the capability to customize it to export your own custom packages. We will use this configuration (recommended) to manage our export package sample.collections.api.

You can download servletbridge_step6-servletbridge.extensionbundle.zip witch contains projects explained in this section.

init-param extendedFrameworkExports

To customize your own custom export packages, it’s very easy. It’s done into the web.xml with the init-param extendedFrameworkExports of the BridgeServlet (or BridgetFilter). Modify web.xml to define sample.collections.api to export like this :

<init-param>
  <param-name>extendedFrameworkExports</param-name>
  <param-value>sample.collections.api</param-value>			
</init-param>

If you do sp_redeploy and you will see the MANIFEST.MF of the org.eclipse.equinox.servletbridge.extensionbundle_1.2.0.jar generated JAR, you wil see that sample.collections.api is exported :

Manifest-Version: 1.0
Export-Package: org.eclipse.equinox.servletbridge; version=1.1, javax.
 servlet; version=2.5, javax.servlet.http; version=2.5, javax.servlet.
 resources; version=2.5, sample.collections.api
Fragment-Host: system.bundle; extension:=framework
Bundle-Version: 1.2.0
Bundle-Name: Servletbridge Extension Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.equinox.servletbridge.extensionbundle

Now you can test it.

Test with Fragment-Host: system.bundle; extension:=framework

At this step you have exported sample.collections.api packages with an OSGi Fragment linked to « system.bundle ». We can test if everything works.

Restart your server (/sp_redeploy + restart server) and type in the console View

ss

The OSGi console display the Short Status of the bundles installed :

...
7 ACTIVE sample.collection1_1.0.0.qualifier

sample.collection1 is ACTIVE (you will notice that sample.collections.api doesn’t appear). You will see too in the console the trace :

Register collection ID=1, label=Collection 1

which means sample.collection1 has registered an instance of ICollection in the CollectionsRegistry. Go at http://localhost:8080/bridge/collections URL to see the registered collection :

Stop the sample.collection1 bundle with OSGi console :

osgi> stop 7
Un-Register collection ID=1, label=Collection 1

The last trace show that the ICollection is unregistered from the CollectionsRegistry. Go at http://localhost:8080/bridge/collections URL :

The collection has disappeared from the list. Restart the sample.collection1 bundle with OSGi console :

osgi> start 7
Register collection ID=1, label=Collection 1

and check the collection appears in the list.

Some improvement

In this last section we will improve a little the collection sample. You can download servletbridge_step6-final.zip witch contains projects explained in this section.

Display bundle ID + bundle symbolicName

Here we use data from the MANIFEST.MF for teh ID+label of teh IColelction. Modify Activator#start method of the sample.collection1 bundle like this :

public void start(BundleContext bundleContext) throws Exception {
	Activator.context = bundleContext;

	Bundle bundle = bundleContext.getBundle();
	String id = String.valueOf(bundle.getBundleId());
	String label = bundle.getSymbolicName();
		
	collection = new DefaultCollection(id, label);
	CollectionsRegistry.getRegistry().registerCollection(collection);
		
}

sample.collection2

Here we will create a second sample.collection bundle. ,To do that :

  • Copy/Paste bundle sample.collection1 to sample.collection2.
  • modify Java package to sample.collection2.internal
  • modify bundle ID with sample.collection2.
  • modify config.ini to add sample.collection2 as a bundle OSGi:
    ,${workspace_loc}/sample.collection2

Restart your server (/sp_redeploy + restart server). You will this trace :

Register collection ID=7, label=sample.collection1
Register collection ID=8, label=sample.collection2

The two collections was registered. Type in the console View

ss

The OSGi console display the Short Status of the bundles installed :

...
7 ACTIVE sample.collection1_1.0.0.qualifier
8 ACTIVE sample.collection2_1.0.0.qualifier

The console show that there are 2 collections started. Go at http://localhost:8080/bridge/collections URL to show the two registered collections :

Conclusion

In this article we have seen how share a singleton between WEB Application context and OSGi context by using :

Fragment-Host: system.bundle; extension:=framework

and export well packages in this OSGi fragment.

This Collection sample show you that it can be interesting to manage Collection with OSGi to start/stop it with OSGi console. This feature is very interesting :

  • In development mode : no need to restart your HTTP server each time you modify the code of an collection. This feature is very interesting when your HTTP server take a long time to start.
  • In production mode : no need to build a big EAR to fix problem for one collection. More it’s possible to install a collection-patch with OSGi console which should fix some problems WITHOUT stopping the HTTP server.
Catégories :Equinox ServletBridge
  1. carmelo
    mars 10, 2011 à 2:48

    Hi Angelo … hope this is the right place where i can ask a question…

    First of all thanks for the wonderful tutorial…
    I have developed an rcp application with some core plugins.
    some plugins will contribute to UI … so they import org.eclipse.ui (and all its dependency).
    Clearly I don’t need to use any of the ui staff … but will be enough to have the plugin resolved (started) so that I could use the “helper” singleton call initialized by the activator …

    How can I do this? Is it possible …

    I’m using eclipse helios, and in my dependency for the ui I have the osgi 3.6.1. how can I mix this with the 3.3 version already present in the bridge

    I have tried to replace it but clearly the servletbridge will fail to be resolved …
    Sorry again if I’m asking in the wrong place.
    Ciao
    Carmelo

    • mars 10, 2011 à 3:01

      Hi carmelo,

      I don’t understand why you speak about RCP application. Servletbrige is done for WEB context (perhaps you are using RAP?) Sorry I cannot help you.

      Regards Angelo

  2. carmelo
    mars 10, 2011 à 3:05

    sorry probably i wasn’t clear …

    i have some plugin in my rcp … and i would love to use those plugins where i have already developed some logic …

    so i will just access the plugin from my servlet to get the methods i need.

    the only problem i have is the dependecy on the eclipse.ui …

    i believe i could import the ui … resolve it … with no use from the ui point of view … but still need to solve the osgi dependency

  3. mars 10, 2011 à 3:12

    OK I understand your problem. I have never used servletbridge with Helios. The bridge.war that you can download is very old. I think you should post your question to equinox forum.

  4. carmelo
    mars 10, 2011 à 3:13

    thx 😉

  5. janvier 16, 2014 à 10:04

    How could I get a reference to a OSGI bundle context from a Servlet in the WAR if deployed in this fashion?

  1. septembre 10, 2010 à 3:45
  2. septembre 10, 2010 à 3:47

Laisser un commentaire