Eclipse RCP/RAP with Spring DM, Spring Data JPA and Remoting [step2]
In [step1], we have initialized Spring DM. At this step we can start using Spring DM features. One of goal of Spring DM is to give the capability to any OSGi bundles, to declare Spring bean in XML Spring file stored in their META-INF/spring folder. Spring DM provides a Spring Extender bundle which :
- load XML Spring file for each OSGi bundles which starts. We will check that in the Start Simple Client bundle section.
- unload XML Spring file for each OSGi bundles which stops.We will check that in the Stop Simple Client bundle section.
We will check this feature in this article by developing a Simple OSGi Bundle which uses Spring fr.opensagres.simpleclient to create an instance of a Thread :
- the bundle hosts a Thread class which display in the System Out console a message :
public class FindAllUsersThread extends Thread { @Override public void run() { while (!super.isInterrupted()) { System.out.println("Call FindAllUsersThread#run()"); } } }
- this Thread class will be declared in a Spring bean in the META-INF/spring/module-context.xml Spring file of the bundle. The start/interrupt of the Thread will be managed by the Spring:
<bean id="FindAllUsersThread" class="fr.opensagres.simpleclient.FindAllUsersThread" init-method="start" destroy-method="interrupt" />
Download
You can download eclipsespring_step2.zip which contains the following explained projects :
- fr.opensagres.simpleclient : OSGi bundle simple client which hosts a Spring file which declares a thread in a Spring bean.
- fr.opensagres.config.log4j : OSGi fragment which configures log4j.
- TargetPlatform: simple project which hosts the Spring DM JARS, the target definition and launch.
To use this zip, unzip it :
- import this 3 projects in a workspace.
- open the TargetPlatform/eclipsespring.target file and click on Set as Target Platform.
- select TargetPlatform/launch/Simple OSGi client.launch and Run it.
Simple Client Bundle
In this section we will create the OSGi bundle fr.opensagres.simpleclient which hosts in the META-INF/spring/module-context.xml Spring file which declares a thread in a Spring bean:
Create OSGi bundle
To create an OSGi bundle, go at the menu File/New/Other… -> Plug-in Development/Plug-in Project:
Click on Next button, and fill project name with fr.opensagres.simpleclient :
Click on Next button, and deselect the whole options :
Click on Finish button to create the project:
FindAllUsersThread class
Create the fr.opensagres.simpleclient.FindAllUsersThread class which display a message every 5 seconds like this:
package fr.opensagres.simpleclient; public class FindAllUsersThread extends Thread { private static final long TIMER = 5000; @Override public void run() { while (!super.isInterrupted()) { try { System.out.println("Call FindAllUsersThread#run()"); } catch (Throwable e) { e.printStackTrace(); } finally { try { if (!super.isInterrupted()) sleep(TIMER); } catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); } } } } @Override public synchronized void start() { System.out.println("Start Thread FindAllUsersThread"); super.start(); } @Override public void interrupt() { System.out.println("Interrupt Thread FindAllUsersThread"); super.interrupt(); } }
The start/interrupt method of Thread is override to display a message.
Rule 1: XML Spring file in META-INF/spring
Rule 1: by default, Spring DM extender observes each bundles and when a bundle starts, it checks if there is XML Spring to load in their META-INF/spring folder.
Create the META-INF/spring/module-context.xml like this :
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="FindAllUsersThread" class="fr.opensagres.simpleclient.FindAllUsersThread" init-method="start" destroy-method="interrupt"/> </beans>
- when the bean is loaded, it creates an instance of fr.opensagres.simpleclient.FindAllUsersThread and call the FindAllUsersThread #start() method.
- when the bean is unloaded, it calls the FindAllUsersThread #interrupt() method.
Run
At this step we add fr.opensagres.simpleclient in the OSGi launch to play with him.
Select simpleclient
Modify the Simple OSGi Client launch to select the fr.opensagres.simpleclient bundle:
Run the Simple OSGi Client launch and you will see in the console :
Start Thread FindAllUsersThread
You will see in the console every 5 seconds the following message :
Call FindAllUsersThread#run()
If you type ss you will see the bundles :
ss Framework is launched. id State Bundle ... 44 ACTIVE fr.opensagres.simpleclient_1.0.0.qualifier
In my case the fr.opensagres.simpleclient has 44 ID.
Stop Simple Client bundle
Stop the fr.opensagres.simpleclient by typing in the OSGi console :
stop 44
You will see in the OSGi console:
stop 44 199857 [Timer-1] INFO org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext - Unpublishing application context OSGi service for bundle Simpleclient (fr.opensagres.simpleclient) ... Interrupt Thread FindAllUsersThread ...
This trace shows you, that when bundle is stopped, Spring extender bundle unload the Spring bean and call FindAllUsersThread#interrup().
Start Simple client bundle
Start the fr.opensagres.simpleclient by typing in the OSGi console :
start 44
You will see in the console :
osgi> start 44 ... osgi> 240779 [SpringOsgiExtenderThread-3] INFO org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext - Refreshing org.springframework.osgi.context.support.OsgiBundleXmlApplicationContext@7eb6e2: display name [OsgiBundleXmlApplicationContext(bundle=fr.opensagres.simpleclient, config=osgibundle:/META-INF/spring... Start Thread FindAllUsersThread Call FindAllUsersThread#run()
This trace shows you, that when bundle is started, Spring extender bundle load the Spring bean and call FindAllUsersThread#start() to start the thread.
Default Auto-Start=false
As we have seen, Spring file are loaded when bundle is started. If you see the OSGi launch configuration, you can notice that Default Auto-Start is setted to true :
It means that OSGi bundles are started when OSGi container is launched. But this configuration is not optimized because the OSGi container start the all bundles
although you could have some bundles which must be started. In Eclipse, Plug-In, Eclipse RCP context, the launch has Default Auto-Start is setted to false.
Here we will change Default auto start to false. Before doing that :
Modify Default Auto-Start to false:
Run the OSGi launch. You will notice that none OSGi bundles are started (OSGi console displays just >osgi)
Rule 2: Spring extender Auto-Start=true
Modify the Spring extender org.springframework.osgi.extender configuration with :
- Start Level to 5.
- Auto-Start to true.
Here Start Level is setted to 5 to start the Spring DM extender after other bundles starts. It’s just for improving the starts of the OSGi container.
Start OSGi launch, you will see some logs of Spring DM extender but our Thread of fr.opensagres.simpleclient is not started.
Rule 3: Bundles with XML Spring Auto-Start=true
Modify the bundle which contains (XML Spring file) fr.opensagres.simpleclient configuration with :
- Auto-Start to true.
Start OSGi launch, you will notice that Thread is created and displays message on the console.
Conclusion
In this article we have seen that Spring DM extender is used to load/unload Spring XML file declared in a bundle fr.opensagres.simpleclient :
- when the bundle is started, Spring DM extender load the Spring bean.
- when the bundle is stopped, Spring DM extender unload the Spring bean.
Here rules with Spring DM that we have seen :
- Rule 1: by default Spring DM extender org.springframework.osgi.extender load/unload XMl Spring for bundles which hosts XML Spring file in their META-INF/spring folder.
- Rule 2: Spring DM extender org.springframework.osgi.extender must be configured with Auto-Start=true and Start Level=5.
- Rule 3: Bundles which hosts XML Spring must be configured with Auto-Start=true.
In [step3] we will see how to use Spring DM to publish/consume services in the OSGi registry services by declaring it in Spring file.
Hi Angelo, thanks for your posts and tutorial. I’m trying to migrate your example by using Eclipse Gemini Blueprint instead of Spring DM. I use Gemini Blueprint 1.0.2 and Spring 3.1.2 and I put the dependencies in the Target Platform and it run properly, but when I try to start the simpleclient bundle this exception occurs:
….
7946 [EclipseGeminiBlueprintExtenderThread-1] ERROR org.eclipse.gemini.blueprint.extender.internal.blueprint.activator.BlueprintLoaderListener – Application context refresh failed (OsgiBundleXmlApplicationContext(bundle=com.intelliment.example.blueprint.simpleclient, config=bundleentry://4.fwk2133512606/OSGI-INF/blueprint/module-context.xml))
java.lang.NoClassDefFoundError: org/springframework/asm/ClassVisitor
….
Do you have any idea why it happens? I’ve already check that spring-asm bundle is loaded and active.
Thanks in advance.
Hi again,
Finally I carried out the integration with Gemini Blueprint. The error I got is due to I put the Spring 3 dependency in the target and these are not necessary because Gemini bring their own.
Regards.
Hi, could you tell me where I can download the .zip file attached to this post? Thanks
You cannot -( since dropbox doesn’t provide capability to download files.