Accueil > DynaResume, OSGi, Spring DM, Spring Remoting > Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step11]

Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step11]


Dans le billet précédant [step10] nous avons mis en place Spring Remoting coté client (client avec/sans OSGi) qui fait appel (via Remoting HTTP Invoker) au service UserService exposé par l’application WEB classique dynaresume-server. Dans ce billet nous allons transformer l’application WEB classique en bundle OSGi.

Voici un schéma de ce que nous allons effectuer dans ce billet concernant le bundle OSGi org.dyanresume.remoting.exporter.http qui va remplacer l’application WEB classique dynaresume-server :

Ce schéma montre que nous allons :

  • créer le bundle org.dyanresume.remoting.exporter.http qui s’occupe de :
    1. récupérer du registre de services OSGi, le service UserService qui a été enregistré par le bundle org.dynaresume.services.impl. Ceci s’effectue déclarativement dans le fichier XML Spring module-osgi-context.xml.
    2. exposer via Remoting HTTP Invoker le service UserService. Ceci s’effectue déclarativement dans le fichier XML Spring module-context.xml.
  • enrichir la Target Platform avec les bundles Spring WEB Extender, Tomcat et/ou Jetty. Le serveur Tomcat/Jetty est un bundle OSGi. Il n’y a pas besoin d’installer un Tomcat ou Jetty classique.

On peut remarquer dans ce schéma que l’implémentation des services ne se trouvent pas dans l’application WEB. Il est récupéré via le registe de services OSGi. Ce procédé permet ainsi d’arrêter/lancer ou d’installer un nouveau bundle qui fournit l’implémentation des services sans arrêter l’application WEB.

Nous verrons ensuite comment utiliser nos différents bundles OSGi à travers des launch (Run) pour avoir :

Vous pouvez télécharger org.dynaresume_step11-spring-osgi-remoting.zip qui contient les projets expliqués dans ce billet :

  • tous les projets (bundles OSGi + Target Platform créés jusqu’à maintenant) expliqués dans le pré-requis.
  • org.dyanresume.remoting.exporter.http, bundle de remoting serveur qui est l’application WEB qui expose les services via Remoting HTTP Invoker.
  • le projet spring-target-platform est enrichi :

Spring Dynamic Module – Web support

Dans ce billet nous allons mettre en place le bundle OSGi org.dynaresume.remoting.exporter.http qui est une application WEB déployé dans un serveur (Tomcat ou Jetty). Pour des informations détaillées concernant le sujet OSGi et WEB avec Spring DM, je vous conseille de lire le chapitre Chapter 9. Web Support.

Lorsque j’ai commencé à rédiger ce billet, j’avais du mal à voir comment une application WEB déployé dans un conteneur WEB (serveur) pouvait cohabiter avec un conteneur OSGi. En effet d’un coté nous avons un conteneur OSGi (Equinox) qui hébérge des bundles OSGi et de l’autre coté nous avons un conteneur WEB (serveur Tomcat, Jetty) qui héberge des applications WEB. Comment ces 2 conteneurs peuvent-ils cohabiter ensemble? La réponse est que tout est bundle, autrement dit :

  • le serveur (Tomcat, Jetty) est un bundle OSGi.
  • l’application WEB est un bundle OSGi.

Le conteneur OSGi orchestre tous ces bundles OSGi.

Spring Web Extender

Pour lancer notre application WEB org.dynaresume.remoting.exporter.http qui est un bundle OSGi, il faut :

  1. démarrer le bundle OSGi serveur (Tomcat/Jetty). Spring DM fournit les bundles Tomcat et Jetty dans sa distribution Spring DM.
  2. déployer l’application WEB dans le bundle OSGi serveur.

La première étape est assez simple. En effet, le conteneur OSGi (Equinox) lance le bundle OSGi serveur qui est présent dans la Target Platform (Bundle OSGi Tomcat ou Jetty). La seconde étape consiste à détecter les bundles OSGi qui doivent être déployés en tant qu’application WEB dans le bundle OSGi serveur. Mais comment distinguer un bundle OSGi simple à un bundle OSGi de type application WEB? En effet dans notre cas seul le bundle org.dyanresume.remoting.exporter.http qui expose les services par Remoting HTTP doit être déployé dans le bundle OSGi serveur.

Un bundle OSGi de type application WEB est tout simplement un bundle qui contient un répertoire WEB-INF qui contient un fichier XML web.xml comme une application WEB classique.

Ce mécanisme qui permet de détecter si un bundle OSGi doit être déployé ou non dans le bundle OSGi serveur est géré par le bundle Spring Web Extender d’ID org.springframework.osgi.web.extender. Son rôle est de scruter tous les bundles OSGi hébergés dans le conteneur OSGi (Equinox) et vérifie pour chacun d’eux si ils contiennent un fichier XML WEB-INF/web.xml. Dans ce cas-ci le bundle est déployé dans le bundle OSGi serveur.

Prérequis

Pour démarrer ce billet nous allons repartir :

  • des projets du billet [step10], en ne prenant plus compte de l’application WEB classique dynaresume-server.
  • du bundle org.dynaresume.services.impl de [step8].

Vous pouvez trouver ces projets dans le zip org.dynaresume_step11-start.zip qui contient les projets:

  • org.dynaresume.config.log4j, bundle de configuration de Log4j.
  • org.dynaresume.config.remoting.importer.http, bundle de configuration de remoting client.
  • org.dynaresume.domain, bundle domaine.
  • org.dynaresume.remoting.importer.http, bundle de remoting client.
  • org.dynaresume.services, bundle API services.
  • org.dynaresume.services.impl, bundle Implémentation services.
  • org.dynaresume.simpleosgiclient, bundle OSGi client.
  • spring-target-platform, projets qui contient tous les JARs de la Target Platform.

Bundle org.dynaresume.remoting.exporter.http

Dans cette section nous allons « transformer » l’application WEB classique dynaresume-server en bundle OSGi en créant le bundle org.dynaresume.remoting.exporter.http. Ce dernier est une application WEB, qui à pour rôle d’exporter les services en remoting HTTP. Ce bundle sera déployé (via le bundle Spring Web Extender) dans un serveur bundle OSGi (Tomcat ou Jetty).

A la différence de l’application WEB classique dynaresume-server, le bundle org.dynaresume.remoting.exporter.http ne contiendra pas l’implémentation des services. L’implémentation des services se trouve dans le bundle org.dynaresume.services.impl qui enregistre l’implémentation du service UserServiceImpl dans le registre de services OSGi. Le bundle org.dynaresume.remoting.exporter.http récupère l’implémentation du service du registre de services OSGi et l’exporte ensuite via Remoting HTTP.

Le fait de ne pas mettre les implémentations des services dans le bundle qui expose par remoting HTTP les services est un un choix très intéressant. Il permet par exemple d’installer une nouvelle version du bundle service org.dynaresume.services.impl sans arrêter le bundle org.dynaresume.remoting.exporter.http, autrement dit sans arrêter l’application WEB.

Target Platform

Avant de démarrer le développement du bundle OSGi (application WEB) org.dynaresume.remoting.exporter.http, nous devons ajouter à la Target Platform les JARs nécéssaire au bon fonctionnement d’une applcation WEB. Nous avons notemment besoin du JAR org.springframework.web.servlet-2.5.6.A.jar (bundle org.springframework.web.servlet) car le bundle org.dynaresume.remoting.exporter.http a besoin de définir la Servlet (Spring DispatcherServlet) comme ce que nous avons effectué dans le billet [step9].

Pour éviter d’avoir tous les JARs Spring au même niveau dans le projet Simple spring-target-platform et qu’à la fin on ne s’y retrouve plus, j’ai décidé de créer un répertoire server dans ce projet qui contient les JARs nécéssaires aux serveur. Pour cela, créez un répertoire server dans le projet spring-target-platform et ajoutez y les JARs de la distribution Spring DM :

JAR Rôle
lib/org.springframework.web.servlet-2.5.6.A.jar Fournit la Servlet Spring Dispatcher
dist/spring-osgi-web-1.2.0.jar Fournit la classe ApplcationContext OsgiBundleXmlWebApplicationContext qui est utilisé dans un contexte OSGi + WEB
dist/spring-osgi-web-extender-1.2.0.jar Spring Web Extender

Ajoutez à la Target Platform le répertoire server comme expliqué ici.

Dans la page Add Content du wizard, ajoutez la valeur ${workspace_loc}/spring-target-platform/server pour faire référence au JARs du répértoire server du projet du workspace. Cliquez sur OK :

REMARQUE : Le JAR spring-osgi-web-extender-1.2.0.jar est le bundle Spring Web Extender. Il n’est pas nécessaire pour la compilation de notre bundle mais nous en aurons besoin au lancement du conteneur OSGi.

Initialisation bundle org.dynaresume.remoting.exporter.http

Créez le bundle org.dynaresume.remoting.exporter.http en créant l’Activator dans le package internal (soit org.dynaresume.remoting.exporter.http.internal.Activator) et en mettant les traces start/stop :

package org.dynaresume.remoting.exporter.http.internal;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

	public void start(BundleContext context) throws Exception {
		System.out.println("Start Bundle [" + context.getBundle().getSymbolicName() + "]");
	}

	public void stop(BundleContext context) throws Exception {
		System.out.println("Stop Bundle [" + context.getBundle().getSymbolicName() + "]");

	}

}

Mise en place de Spring Remoting (HTTP)

Dans cette section nous allons expliquer pas à pas comment mettre en place le support de Remoting Spring’s HTTP invoker dans notre bundle OSGi de type application WEB. Cette mise en place suit les mêmes principes que la mise en place de Spring Remoting (HTTP) dans une application WEB classique, mais la configuration diverge un peu dù au contexte OSGi.

Comment ca marche?

Notre service sera accéssible via l’URL http://localhost:8080/dynaresume-server/remoting/UserService.

Servlet remoting

Cette URL est traitée par la servlet remoting (nommée remoting), UNIQUE Spring org.springframework.web.servlet.DispatcherServlet, définit dans le web.xml de l’application WEB :

<servlet>
	<servlet-name>remoting</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>

Cette servlet remoting est à l’écoute des URL de type /remoting/* :

<servlet-mapping>
	<servlet-name>remoting</servlet-name>
	<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
module-context.xml (=remoting-servlet.xml)

La servlet remoting dispatche sur le bon service demandé. Le dernier token UserService de l’URL définit le service que le client souhaite appeler. Ce token est en fait le nom d’un bean Spring définit dans le fichier XML Spring de configuration META-INF/spring/module-context.xml qui expose le service via HTTPInvoker :

<bean name="/UserService"
	class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
	<property name="service" ref="userService" />
	<property name="serviceInterface" value="org.dynaresume.services.UserService" />
</bean>

Le fichier module-context.xml est identique à celui de remoting-servlet.xml). La définition du bean UserService du fichier META-INF/spring/module-context.xml utilise org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter qui permet d’exposer le service par HTTP. 2 propriétés doivent être renseignées à ce bean singleton :

  • Le nom de l’interface du service à exporter qui est renseigné par le setter HttpInvokerServiceExporter#setServiceInterface(Class serviceInterface) déclarativement :
    <property name="serviceInterface" value="org.dynaresume.services.UserService" />
  • L’implémentation du service (instance de UserServiceImpl) renseigné par le setter HttpInvokerServiceExporter#setService(Object service) avec l’injection de dépendance faisant référence à un autre bean d’ID userService:
    	<property name="service" ref="userService" />
module-osgi-context.xml (~applicationContext-xml)

Le bean d’ID userService retourne une instance de la classe org.dynaresume.services.impl.UserServiceImpl. A la différence de l’application WEB classique qui s’occupe d’instancier le service, le bean d’ID userService est recherché dans le registre de services OSGi :

<osgi:reference id="userService" interface="org.dynaresume.services.UserService" timeout="1000" />

C’est le bundle org.dynaresume.services.impl qui s’occupe d’instancier UserServiceImpl et d’enregistrer cette instance dans le registre de services OSGi.

servlet remoting/init-param

Les 2 fichiers XML Spring de configuration stockés dans le répertoire META-INF/spring du bundle doivent être chargé. Pour cela on indique à la servlet remoting les paramètres :

  • contextConfigLocation qui indique le chemin des fichiers Spring. Dans notre cas, ce paramètre doit être renseigné avec la valeur META-INF/spring/*.xml.
  • contextClass qui indique la classe ApplicationContext à utiliser pour charger les fichiers Spring XML. Dans notre cas, ce paramètre doit être renseigné avec la valeur org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext qui permet de gérer le chargement des fichiers XML Spring dans un contexte OSGi et WEB.

Ceci se traduit par les élements XML init-param suivant :

<servlet>
	<servlet-name>remoting</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>META-INF/spring/*.xml</param-value>
	</init-param>
	<init-param>
		<param-name>contextClass</param-name>
		<param-value>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>

web.xml

Créez dans le répertoire WEB-INF (a créé) du bundle, le fichier XML web.xml comme suit :

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
	xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>dynaresume-server</display-name>
	<servlet>
		<servlet-name>remoting</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>META-INF/spring/*.xml</param-value>
		</init-param>
		<init-param>
			<param-name>contextClass</param-name>
			<param-value>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>remoting</servlet-name>
		<url-pattern>/remoting/*</url-pattern>

	</servlet-mapping>

</web-app>

module-context.xml

Créez le fichier module-context.xml dans le répertoire META-INF/spring du bundle comme suit :

<?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-2.5.xsd">


	<bean name="/UserService"
		class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
		<property name="service" ref="userService" />
		<property name="serviceInterface" value="org.dynaresume.services.UserService" />

	</bean>

</beans>

module-osgi-context.xml

Créez le fichier module-osgi-context.xml dans le répertoire META-INF/spring du bundle comme suit :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi"
	xsi:schemaLocation="http://www.springframework.org/schema/osgi  
       http://www.springframework.org/schema/osgi/spring-osgi-1.0.xsd
       http://www.springframework.org/schema/beans   
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<osgi:reference id="userService" interface="org.dynaresume.services.UserService"
		timeout="1000" />

</beans>

MANIFEST.MF

A cette étape nous avons fini la configuration des fichiers XML Spring, mais il reste à :

  • indiquer le nom du contexte de l’application WEB avec dynaresume-server.
  • définir explicitement les dépendances (via Import Package) aux bundles de remoting HTTP, de servlet Spring, et de la classe User et interface UserService.

Web-ContextPath

Le contexte de l’application WEB est dynaresume-server dans notre cas. Celui-ci est determiné par la méta donnée Web-ContextPath du fichier META-INF. Ajoutez ce contenu dans le fichier MANIFEST-MF :

Web-ContextPath: dynaresume-server

Dépendances

Ajoutez les dépendances requises via Import Package (que j’ai identifié au fur et à mesure en relançant le bundle):

  • org.dynaresume.domain
  • org.dynaresume.services

et celle de Spring :

  • org.aopalliance.aop
  • org.springframework.aop
  • org.springframework.aop.framework
  • org.springframework.osgi.web.context.support
  • org.springframework.remoting
  • org.springframework.remoting.httpinvoker
  • org.springframework.remoting.support
  • org.springframework.web.servlet

Ce qui donne :

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Dynaresume Server
Bundle-SymbolicName: org.dynaresume.remoting.exporter.http
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: org.dynaresume.remoting.exporter.http.Activator
Import-Package: org.aopalliance.aop;version="1.0.0",
 org.dynaresume.domain,
 org.dynaresume.services,
 org.osgi.framework;version="1.3.0",
 org.springframework.aop;version="2.5.6.A",
 org.springframework.aop.framework;version="2.5.6.A",
 org.springframework.osgi.web.context.support;version="1.2.0",
 org.springframework.remoting;version="2.5.6.A",
 org.springframework.remoting.httpinvoker;version="2.5.6.A",
 org.springframework.remoting.support;version="2.5.6.A",
 org.springframework.web.servlet;version="2.5.6.A"
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Web-ContextPath: dynaresume-server

Launch (Run)

A cette étape nous avons un ensemble de bundles OSGi provenant :

  • du Workspace (nos bundles org.dynaresume.*).
  • de la Target Platform (Spring DM, Tomcat Jetty….).

Avec tous ces bundles nous pouvons gérer différentes architectures (Full CLient, Client/Serveur) sans changer le code de nos bundles. Nous avons effectué plusieurs choix sur le découpage de nos bundles comme :

  • scinder les bundles API services et Implémentation en 2 bundles distincts.
  • dissocier le bundle « Remoting Exporter HTTP » au bundle d’Implémentation de services.

Nous allons voir à travers les launch, tout l’interêt de ce choix de découpage qui permet de gérer plusieurs architectures avec les mêmes bundles client. Pour gérer cela, il suffit de sélectionner un ensemble de bundles et ensuite de les lancer dans un conteneur OSGi (Equinox). La sélection de ces ensembles de bundles s’effectue via des launch. Voici les différents launch que nous allons créer (que j’ai d’ailleurs exporté et que j’ai mis dans le projet spring-target-platform) :

Launch Serveur (Tomcat/Jetty)

Les serveurs Tomcat et Jetty sont des bundles OSGi qui seront lancés via le containeur OSGi (Equinox). L’utilisation de Tomcat ou Jetty consiste à ajouter à la Target Platform les bundles requis pour chacun des serveurs et ensuite de les sélectionner dans les launch. La distribution Spring DM propose des JARs Tomcat et Jetty mais malheursement ils sont incomplets :

  • Concernant Tomcat, il manque les JARs Jasper.
  • Concernant Jetty, il manque le JAR servlet API 2.5.

Pour retrouver la plupart de ces JARs, j’ai utilisé le site WEB SpringSource Enterprise Bundle Repository, repository de bundles de Spring qui intègre un moteur de recherche (ex : tappez Tomcat, Jasper, JSP….dans le champs de recherche). Mails le problème de ce site est qu’il ne fournit pas toutes les versions des bundles. C’est le cas pour Jasper 5.5 requis qui n’est pas fourni par ce site. Pour télécharger le bundle Jasper 5.5 j’ai du utilisé maven.

Si vous ne souhaitez pas vous embêter à télécharger les JARs manquant, le zip org.dynaresume_step11-spring-osgi-remoting.zip contient déja tous ces JARs.

Je me rends compte à ce stade que la solution la plus propre pour démarrer un projet avec Spring DM est d’utiliser maven pour déterminer dans un fichier pom.xml les dépendances requises et de laisser maven télécharger tous les bundles requis. C’est d’ailleurs ce qui a été effectué dans le projet DynaResume.

Launch Server Tomcat 5.5

Ici nous souhaitons déployer le bundle OSGi application WEB org.dynaresume.remoting.exporter.http dans un serveur Tomcat 5.5. Pour cela nous devons :

Voici un schéma de cette arhcitecture qui montre les bundles à sélectionner dans le launch :

JAR Tomcat

La distribution Spring DM fournit 2 JARs :

JAR Description
lib/catalina.osgi-5.5.23-SNAPSHOT.jar
lib/catalina.start.osgi-1.0.0.jar

Mais malheursement ils ne suffisent pas. En effet si vous ajoutez uniquement ces 2 JARs à la Target Platform et que vous les sélectionnez ensuite dans le launch, vous aurrez l’erreur suivante :

1579 [Timer-2] INFO org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'remoting': initialization completed in 125 ms
1594 [Timer-2] INFO org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/dynaresume-server] - Marking servlet jsp as unavailable
1594 [Timer-2] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/dynaresume-server] - Error loading java.net.FactoryURLClassLoader@c8e4de org.apache.jasper.servlet.JspServlet
java.lang.ClassNotFoundException: org.apache.jasper.servlet.JspServlet
...

Cette erreur signifie que Jasper est requis (alors que nous n’avons pas de JSP???). Cette erreur n’est pas grave en soit car le bundle OSGi remoting coté serveur fonctionne correctement. Mais étant puriste, j’ai essayé de régler le problème et au final il manque les JARs suivants :

JAR Téléchargement
jasper.osgi-5.5.23-20081003.025534-28.jar via MAVEN
com.springsource.javax.el-1.0.0.jar SpringSource Enterprise Bundle Repository
com.springsource.javax.servlet.jsp-2.1.0.jar SpringSource Enterprise Bundle Repository

J’ai eu beaucoup de mal à trouver le JAR Jasper jasper.osgi-5.5*. En effet SpringSource Enterprise Bundle Repository ne fournit que les JARs Jasper de version 6*. J’ai pu le récupérer en utilisant Maven. Si vous connaissez maven (et le repository Spring) voici la dépendance que j’ai utilisé :

<dependency>
	<groupId>org.springframework.osgi</groupId>
	<artifactId>jasper.osgi</artifactId>
	<version>5.5.23-SNAPSHOT</version>
</dependency>

Les 2 autres JARs (JSP et EL) sont aussi nécessaires car le JAR Jasper y dépend.

Target Platform

Créez le répertoire tomcat5.5 dans le répertoire server du projet spring-target-platform. Ajoutez les 5 JARs Tomcat requis :

Ajoutez à la Target Platform le répertoire tomcat5.5 comme expliqué ici.

Dans la page Add Content du wizard, ajoutez la valeur ${workspace_loc}/spring-target-platform/server/tomcat5.5 pour faire référence aux JARs du répértoire tomcat5.5 du projet du workspace. Cliquez sur OK :

Launch OSGi DynaResume – Server Tomcat 5.5

Nous pouvons nous occuper de créer le launch. Pour cela accédez au menu Run Configurations….

Ceci ouvre la fenêtre de Run Configurations. Si vous avez utilisé le projet spring-target-platform du zip. Les 4 launch doivent apparaître :

Vous pouvez les utiliser directement. Dans le cas contraire pour créer une nouvelle configuration, sélectionnez le noeud OSGi Framework puis clic droit. Ceci ouvre le menu contextuel :

Sélectionnez l’item new qui va créer une nouvelle configuration :

Cette action créé une nouvelle configuration qui sélectionne tous les bundles du Workspace et de la Target Platform. Renommez la configuration avec OSGi DynaResume – Server Tomcat 5.5.

Dé-selectionnez les bundles suivants :

  • les bundles clients du Workspace :
    • org.dynaresume.config.remoting.importer.http
    • org.dynaresume.remoting.importer.http
    • org.dynaresume.simpleosgiclient
  • les bundles Jetty de la Target Platform (si vous avez déja ajouté ces JARs à la Target Platform) :
    • com.springsource.javax.servlet*2.5
    • com.springsource.net.sf.cglib
    • org.mortbay.jetty.server
    • org.mortbay.jetty.util
    • org.springframework.osgi.jetty.start.osgi
    • org.springframework.osgi.jetty.web.extender.fragment.osgi

Vous pouvez ensuite lancer le launch via le bouton Run qui lancera le serveur Tomcat et déploira l’application WEB.
https://angelozerr.wordpress.com/wp-admin/post.php?action=edit&post=1306&message=10

Launch Server Jetty 6.1.9

Ici nous souhaitons déployer le bundle OSGi application WEB org.dynaresume.remoting.exporter.http dans un serveur Jetty 6.1.9. Pour cela nous devons :

Voici un schéma de cette arhcitecture qui montre les bundles à sélectionner dans le launch :

JAR Jetty

La distribution Spring DM fournit 5 JARs :

JAR Description
lib/com.springsource.net.sf.cglib-2.1.3.jar/strong>
lib/jetty-6.1.9.jar
lib/jetty-util-6.1.9.jar
lib/jetty.start.osgi-1.0.0.jar
lib/jetty.web.extender.fragment.osgi-1.0.1.jar

Mais malheursement ils ne suffisent pas. En effet si vous ajoutez uniquement ces 5 JARs à la Target Platform et que vous les sélectionnez ensuite dans le launch, vous aurrez l’erreur suivante :

osgi> org.osgi.framework.BundleException: The bundle could not be resolved. Reason: Missing Constraint: Import-Package: javax.servlet; version="2.5.0"...

Cette erreur signifie que le bundle API Servlet de version 2.5 n’est pas trouvé. Ce qui est le cas car la distribution ne fournit que la 2.4. En d’autre termes il manque les JARs suivants :

JAR Téléchargement
com.springsource.javax.servlet-2.5.0.jar SpringSource Enterprise Bundle Repository

Pour se rendre compte de ce problème de dépendances avant de lancer le launch, il est possible de cliquer dans la fenêtre de Run Configuration sur le Bouton Validate Bundles :

Après avoir cliqué sur le bouton Validate Bundles, le dialogue Validation s’affiche en indiquant les erreurs de dépendances :

Target Platform

Créez le répertoire jetty6.1.9 dans le répertoire server du projet spring-target-platform. Ajoutez les 6 JARs Jetty requis :

Ajoutez à la Target Platform le répertoire jetty6.1.9 comme expliqué ici.

Dans la page Add Content du wizard, ajoutez la valeur ${workspace_loc}/spring-target-platform/server/jetty6.1.9 pour faire référence aux JARs du répértoire jetty6.1.9 du projet du workspace. Cliquez sur OK :

Launch Server Jetty 6.1.9

Créez une nouvelle configuration OSGi Framework et renommez la en OSGi DynaResume – Server Jetty 6.1.9.

Dé-selectionnez les bundles suivants :

  • les bundles clients du Workspace :
    • org.dynaresume.config.remoting.importer.http
    • org.dynaresume.remoting.importer.http
    • org.dynaresume.simpleosgiclient
  • les bundles Tomcat de la Target Platform (si vous avez déja ajouté ces JARs à la Target Platform) :
    • com.springsource.javax.el
    • com.springsource.javax.servlet*2.4
    • com.springsource.javax.servlet.jsp
    • org.springframework.osgi.catalina.start.osgi
    • org.springframework.osgi.catalina.osgi
    • org.springframework.osgi.jasper.osgi

Vous pouvez ensuite lancer le launch via le bouton Run qui lancera le serveur Jetty et déploira l’application WEB.

Launch Client (Architecture Client/Server)

Ici nous souhaitons lancer le client dans une architecture client/serveur qui fait appel au service UserService exposé par le serveur. Pour cela nous devons créer le launch OSGi DynaResume – Client (Server).

Voici un schéma de cette arhcitecture qui montre les bundles à sélectionner dans le launch :

Créez une nouvelle configuration OSGi Framework et renommez la en OSGi DynaResume – Client (Server).

Dé-selectionnez les bundles suivants :

  • les bundles d’exportation des services et de l’implémentation des services du Workspace :
    • org.dynaresume.remoting.exporter.http
    • org.dynaresume.services.impl
  • les bundles server de la Target Platform :
    • org.springframework.osgi.web
    • org.springframework.osgi.web.extender
    • org.springframework.web.servlet
  • les bundles Tomcat de la Target Platform (si vous avez déja ajouté ces JARs à la Target Platform) :
    • com.springsource.javax.el
    • com.springsource.javax.servlet*2.4
    • com.springsource.javax.servlet.jsp
    • org.springframework.osgi.catalina.start.osgi
    • org.springframework.osgi.catalina.osgi
    • org.springframework.osgi.jasper.osgi
  • les bundles Jetty de la Target Platform (si vous avez déja ajouté ces JARs à la Target Platform) :
    • com.springsource.javax.servlet*2.5
    • com.springsource.net.sf.cglib
    • org.mortbay.jetty.server
    • org.mortbay.jetty.util
    • org.springframework.osgi.jetty.start.osgi
    • org.springframework.osgi.jetty.web.extender.fragment.osgi

Lancez l’application WEB via le launch OSGi DynaResume – Server Tomcat 5.5 ou OSGi DynaResume – Server Jetty 6.1.9.

Lancez le client via le launch créé OSGi DynaResume – Client (Server).

Le client OSGi doit faire appel au service UserService exporté par le serveur (Tomcat ou Jetty) et afficher dans la console OSGi la liste des Users.

Launch Client (Architecture Full Client)

Dans l’architecture Full Client, tous les bundles client et services (API et Implémentation) se retrouvent dans le même conteneur OSGi. Aucun bundles WEB et serveur (Tomcat et Jetty) ne sont nécéssaires.

Voici un schéma de cette arhcitecture qui montre les bundles à sélectionner dans le launch :

Créez une nouvelle configuration OSGi Framework et renommez la en OSGi DynaResume – Full Client.

Dé-selectionnez les bundles suivants :

  • les bundles d’exportation et d’importation des services du Workspace :
    • org.dynaresume.remoting.exporter.http
    • org.dynaresume.remoting.importer.http
    • org.dynaresume.config.remoting.importer.http
  • les bundles WEB (Remoting) de la Target Platform :
    • org.springframework.web
  • les bundles server de la Target Platform :
    • org.springframework.osgi.web
    • org.springframework.osgi.web.extender
    • org.springframework.web.servlet
  • les bundles Tomcat de la Target Platform (si vous avez déja ajouté ces JARs à la Target Platform) :
    • com.springsource.javax.el
    • com.springsource.javax.servlet*2.4
    • com.springsource.javax.servlet.jsp
    • org.springframework.osgi.catalina.start.osgi
    • org.springframework.osgi.catalina.osgi
    • org.springframework.osgi.jasper.osgi
  • les bundles Jetty de la Target Platform (si vous avez déja ajouté ces JARs à la Target Platform) :
    • com.springsource.javax.servlet*2.5
    • com.springsource.net.sf.cglib
    • org.mortbay.jetty.server
    • org.mortbay.jetty.util
    • org.springframework.osgi.jetty.start.osgi
    • org.springframework.osgi.jetty.web.extender.fragment.osgi

Le client OSGi doit faire appel au service UserService récupéré du bundle Services Implémantation et afficher dans la console OSGi la liste des Users.

Conclusion

Dans ce billet nous avons transformé l’application WEB classique qui exporte via Remoting HTTP les services en bundle OSGi. Le découpage de nos bunles OSGi nous permet de gérer plusieurs architectures (Full Client et Client/Serveur).

L’interêt d’avoir transformé l’application WEB en bundle OSGi nous permet de bénéficier des avantages fournis par OSGi comme arrêter/stopper les services de l’application WEB sans arrêter l’application WEB. Ce procédé peut être très bénéfique

  • au niveau développement: dans une grosse application WEB, le temps démarrage peut être tres long. Le développeur qui souhaite tester ses services peut arrêter et relancer son bundle pour le tester sans arrêter le serveur. Dans le cas de grosses application WEB, ce procédé peut apporter un gain de temps considérable (et de motivation aussi, car il n’y a rien de plus déprimant que d’attendre 10 min pour lancer son serveur).
  • au niveau production : un patch sur un service qui corrigerait un bug n’engendre pas l’arrêt du serveur (ceci n’impacte pas les utilisateurs connectés).

Dans le prochain billet nous nous concentrerons sur le développement d’un client basé sur une application Eclipse RCP qui permettra d’afficher la liste des Users dans une liste.

Vous pouvez lire le billet suivant [step12].

  1. nsoufiane
    avril 8, 2010 à 4:17

    Bonjour , tout dabord je tiens a vous féliciter pour la qualité de votre travail . je voulais vous demander si il ne serrait pas possible de voir un peu les fonctionnalités qu’offre SDM (filtage , cardinalités ,list et set (comparateur..), …) surtout avec l’utilisation du httpinvoker car on general ya pas de probleme lors de leurs utilisation lorsque le client et le serveur sont dans un meme conteneur osgi ( full client)

    • avril 8, 2010 à 5:58

      Bonsoir nsoufiane,

      Merci beaucoup pour vos encouragements. Le but de mes billets est de tenter d’expliquer les grandes principes à suivre lorsque l’on souhaite mettre en place un projet avec RCP et Spring DM avec une architecture Domain/Services/DAO.

      Il est vrai que le sujet « filtage , cardinalités ,list et set (comparateur..) » je n’en parle pas beaucoup (les cardinalités ca j’en parle) car durant la rédaction de mes billets je n’en ai pas eu beaucoup besoin. Le sujet « cardinalité » j’en parle dans les billets suivants car dans une architecture client/serveur c’est très important comme vous le dites (le service peut ne pas etre disponible coté serveur).

      Je suis en train de terminer le step19 qui parle des DAO Jpa dans un contexte OSGi. Après je pense que je vais étudier RAP, mais je n’ai encore rien décide.

      Angelo

  2. capt caverne
    juillet 19, 2012 à 10:55

    Bonsoir,

    pour commencer de manière originale, merci a toi et a tes comperes pour vos travaux et le temps que vous consacrez à les détailler.

    J’aurai une petite question sur la partie « web » de springDM : je ne sais pas si tu saurais me dire si geminiweb est toujours « d’actualité » ? J’ai un petit souci pour mettre a jour la mise en place du serveur avec gemini web : le context OsgiBundleXmlWebApplicationContext ne semble pas être dans la distribution. En creusant pour voire comment définir mon context, je ne trouve pas d’exemple ou de site en parlant. Sur les forums, les quelques personnes qui ont eu ce problème ont pour réponse « passe a Virgo » (qui d’ailleurs a lui meme sa propre classe pour definir son context web : ServerOsgiBundleXmlWebApplicationContext je crois)

    Je voulais savoir si vous, vous étiez passé sur virgo ? Si non, avez vous réussi avec la distrib 2.0.1 de geminiweb ou avez vous ajouté les jar spring-osgi-web.jar et spring-osgi-web-extender.jar comme il fallait le faire avec spring DM ?

    Encore merci à votre equipe et bonne continuation

    • juillet 20, 2012 à 12:43

      Bonsoir Stéphane,

      Je n’ai jamais utilisé Virgo, ni geminiweb, donc ca sera difficile pour moi de t’aider. Je suis passé par contre a Eclipse Gemini Blueprint pour Spring DM.
      Concernant la partie WEB je n’en ai pas eu besoin de Spring DM Web extender, car le remoting je l’ai géré avec JAX-RS CXF DOSGi (voir articles https://angelozerr.wordpress.com/about/eclipse_spring/eclipse_spring_dosgi/).

      Bonne continuation.

      Angelo

  1. janvier 5, 2010 à 10:53
  2. janvier 8, 2010 à 6:14
  3. avril 2, 2010 à 3:02

Laisser un commentaire