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

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


Dans les billets précédants [step7] et [step8] nous avons utilisé Spring Dynamic Module pour déclarer la consommation/l’enregistrement du service OSGi UserService dans le registre de services OSGi.

A partir de ce billet nous allons nous concentrer sur la mise en place d’une architecture Client/Serveur, autrement dit :

  • Serveur : les services seront hébergés dans une application WEB (classique, bundle OSGi…) qui exposera le service UserService.
  • Client : le client (main classique, bundle OSGi, Eclipse RCP) appelera le UserService pour récupérer la liste des User qui seront transmis du serveur au client. Le service UserService sera accéssible via l’URL http://localhost:8080/dynaresume-server/remoting/UserService.

Dans ce billet nous allons nous occuper de la partie Serveur en mettant en place une application WEB classique qui expose le service UserService à l’aide de Spring Remoting. Dans le prochain billet nous décrirons comment mettre en place un client (sans OSGi et avec OSGi) qui fera appel au serveur en appelant le service UserService exposé par l’application WEB. Dans les billets futurs nous verrons comment transformer notre application WEB en bundle OSGi pour bénéficier de la technologie OSGi coté serveur.

Voici un schéma de ce que nous allons effectuer dans ce billet :

Ce schéma montre que :

Nous utiliserons un serveur Tomcat pour hébérger notre application WEB.

Prérequis

Avant de démarrer ce billet vous devez :

Initialisation application WEB

Vous pouvez télécharger org.dynaresume_step9-start.zip qui contient les projets expliqués ci dessous :

  • org.dynaresume.domain qui est le bundle OSGi qui contient la classe User.
  • org.dynaresume.services qui est le bundle OSGi qui contient l’interface UserService.
  • dynaresume-server qui est un un « Dynamic Web Project » correspondant à l’application WEB qui va exposer le service UserService. Ce projet fait référénce aux 2 bundles via Java EE Module Dependencies.

Dans cette section nous allons initialiser l’application WEB dynaresume-server avec une page d’accueil HTML en utilisant WTP.

Creation Dynamic Web Project

Ici nous allons creer l’application WEB dynaresume-server dans un projet Dynamic Web Project. Pour cela accédez au menu File/New /Dynamic Web Project :

Ce menu ouvre le wizard suivant :

Renseignez le champs « Project name » avec dynaresume-server, puis cliquez sur le bouton Next :

Le wizard qui permet de configurer les répertoires sources Java du projet s’ouvre. Par défaut src est proposé, cliquez sur le bouton Next :

Le wizard qui permet de configurer le contexte de l’application WEB s’ouvre, cliquez sur le bouton Finish qui permet de générer le projet :

Configuration serveur (Tomcat)

Notre application WEB est initialisé. Nous devons configurer le serveur Tomcat pour lui indiquer de lancer notre application WEB. Pour cela sélectionnez le projet puis clic droit pour ouvrir le menu contextuel. Cliquez sur le menu Run As/Run on Server :

Cette action ouvre le wizard suivant qui permet d’indiquer le serveur que l’on souhaite utiliser. Dans notre cas, sélectionnez Apache/Tomcat v5.5 Server :

Cliquez sur le bouton Next qui ouvre le wizard qui permet d’indiquer le répertoire racine du serveur.

Cliquez sur Browse… puis sélectionner le répertoire racine de Tomcat. Dans mon cas qui est l’installation de base, le répértoire est « C:\Program Files\Apache Software Foundation\Tomcat 5.5 ».

Cliquez sur le bouton Finish, le projet Servers se générent :

Ce projet contient la configuration du lancement de Tomcat pour notre application WEB. Il contient entre autres le fichier server.xml qui définit le contexte Tomcat de l’application WEB :

<Context docBase="dynaresume-server" path="/dynaresume-server" reloadable="true" source="org.eclipse.jst.j2ee.server:dynaresume-server"/>

Le bouton Finish lance le serveur :

  • L’URL est appelée automatiquement . L’erreur 404 s’affiche car les pages welcome définits dans le web.xml n’existent pas.
  • La vue Servers s’ouvre automatiquement et permet de lancer/relancer/arrêter Tomcat.

Lancement application WEB

Ouvrez un navigateur et tappez l’URL http://localhost:8080/dynaresume-server/ et l’erreur 404 s’affiche :

Cette erreur s’explique par le fair que le web.xml définit des pages d’accueils et que aucune n’existe:

<welcome-file-list>
	<welcome-file>index.html</welcome-file>
	<welcome-file>index.htm</welcome-file>
	<welcome-file>index.jsp</welcome-file>
	<welcome-file>default.html</welcome-file>
	<welcome-file>default.htm</welcome-file>
	<welcome-file>default.jsp</welcome-file>
</welcome-file-list>

Pour remédier à cette erreur 404, créez dans le répertoire WebContent, le fichier index.htm avec le contenu suivant :

<html>
	<head>
		<title>DynaResume Server</title>
	</head>
	<body>
		Welcome to DynaResume Server!
	</body>
</html>

Si vous accédez à l’URL http://localhost:8080/dynaresume-server/, la page index.htm s’affiche :

Classes Java

Maintenant que notre application WEB est initialisé nous allons nous occuper des sources Java qui permettent d’exposer le service UserService, autrement dit :

  • la classe org.dynaresume.domain.User. Cette classe provient du bundle OSGi org.dynaresume.domain.
  • l’interface org.dynaresume.services.UserService. Cette interface provient du bundle OSGi org.dynaresume.services.
  • la classe org.dynaresume.services.impl.UserServiceImpl qui est l’implémentation du service UserService. Cette classe sera stockée dans le répertoire src du projet dynaresume-server.

Voici les raisons pour lesquelles nous utilisons les projets bundles OSGi org.dynaresume.domain et org.dynaresume.services :

  • La classe User et l’interface UserService sont communes au client et au serveur (application WEB). Nous aurions pu copier-coller cette classe et l’interface dans le répertoire src de l’application WEB mais si nous avions effectué cela, nous aurrions dù dupliquer la classe/interface pour la partie cliente, ce qui peut être dangereux. En effet dans notre cas l’application WEB fait référence au projet org.dynaresume.domain et org.dynaresume.services, projets qui seront aussi référencés dans les projets client.
  • nous utilisons les bundles OSGi et pas les projets classiques Java car nous souhaitons avoir un client sans OSGi et avec OSGi. Dans le cas d’un client sans OSGi nous pouvons utiliser le bundle OSGi en y faisant référence via le Java Build Path.

Source

Créez dans le projet dynaresume-server, la classe org.dynaresume.services.impl.UserServiceImpl comme suit :

package org.dynaresume.services.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.dynaresume.domain.User;
import org.dynaresume.services.UserService;

public class UserServiceImpl implements UserService {

	private Collection<User> users = null;

	public Collection<User> findAllUsers() {
		if (users == null) {
			users = createUsers();
		}
		return users;
	}

	private Collection<User> createUsers() {
		List<User> users = new ArrayList<User>();
		users.add(new User("angelo", ""));
		users.add(new User("djo", ""));
		users.add(new User("keulkeul", ""));
		users.add(new User("pascal", ""));
		return users;
	}
}

Référence projets Domain/Services

Ajoutez au workspace les projets bundle OSGi org.dynaresume.domain et org.dynaresume.services que vous pouvez trouver dans les zip des billets précédants comme par exemple org.dynaresume_step8-reference-DI.zip. A ce stade la classe UserServiceImpl ne compile pas car les dépendances à User et UserService ne sont pas effectuées.

Java EE Module Dependencies

Notre projet Dynamic Web Project doit dépendre des 2 projets org.dynaresume.domain et org.dynaresume.services. La gestion des dépendances dans un projet de type Dynamic Web Project, ne doit pas s’effectuer via le Java Build Path classique mais par Java EE Module Dependencies.

En effet, si vous utilisez le Java Build Path classique, la compilation s’effectuera correctement, mais à l’execution vous aurrez des erreurs de type ClassNotFoundException.

Pour cela ouvrez la page de Propriété du projet dynaresume-server, pui sélectionnez l’item Java EE Module Dependencies :

Sélectionnez les 2 projets org.dynaresume.domain et org.dynaresume.services puis cliquez sur le bouton OK. Le projet dynaresume-server doit ensuite compiler.

Mise en place de Spring remoting

Vous pouvez télécharger org.dynaresume_step9-spring-remoting.zip qui contient les projets expliqués ci dessous :

  • dynaresume-server, l’application WEB qui expose le service UserService via Spring Remoting.
  • org.dynaresume.domain qui est le bundle OSGi qui contient la classe User.
  • org.dynaresume.services qui est le bundle OSGi qui contient l’interface UserService.

Remoting, c’est quoi?

Dans une architecture client/serveur, le client (Java Main, Bundle OSGi, Eclipse RCP…) doit communiquer avec le serveur pour utiliser les services que ce dernier exporte. Dans notre cas, notre application WEB exportera le service UserService accéssible via l’URL http://localhost:8080/dynaresume-server/remoting/UserService. Lorsque le client appèlera la méthode UserService#findAllUsers() du service exporté par le serveur, la liste des User sera transmises du serveur vers le client. Une étape de sérialisation (côté serveur)/dé sérialisation (côté client) des données User sera nécessaire.

L’article Remoting avec Hessian décrit très bien en introduction ce qu’est le Remoting :

Le remoting est un mécanisme qui permet de mettre en place des applications distribuées en permettant à des composants d’invoquer des traitements sur des autres composants distants.

La mise en place d’un mécanisme de remoting implique plusieurs autres mécanismes, qui sont la sérialisation/désérialisation des objets pour pouvoir les transférer, un mécanisme d’exposition de services et un mécanisme de localisation et d’invocation de ces services.

La communication entre le client et serveur est appelé « Remoting ».

Spring remoting, c’est quoi?

Spring Remoting intègre des supports pour le remoting en utilisant divers technologies. Il permet de s’affranchir des problématiques techniques de la technologie de remoting et de pouvoir déclarer ses services comme des Bean classique. Spring Remoting fournit plusieurs support de remoting (voir FAQ Spring/Remoting) dont :

  • Remote Method Invocation (RMI).
  • Hessian : Hessian est un protocole binaire, basé sur http pour exporter un service. Il est normalement indépendant du langage, mais actuellement principalement utilisé pour des applications Java à Java. .
  • Burlap : Burlap est un protocole basé sur XML et sur http pour exporter un service. Il est normalement indépendant du langage, mais actuellement principalement utilisé pour des applications Java à Java. .
  • Spring’s HTTP invoker : Contrairement à Burlaps ou Hessian qui utilisent des sérialisations binaire et XML indépendantes à Java, HttpInvoker utilise la sérialisation Java standard.
    Cela implique que HttpInvoker ne fonctionne bien evidemment qu’entre deux applications Java, mais aussi que tous les objets qui sont transférés suivent les règles de sérialisation Java : Implémenter l’interface java.io.Serializable ainsi que de définir un serialVersionUID correctement.

    De plus, HttpInvoker n’est disponible qu’avec Spring, il est donc nécessaire que le client et le serveur soient tout les deux basés sur Spring.

  • JAX-RPC
  • JAX-WS
  • JMS

Dans notre cas, nous allons partir sur le support de Remoting Spring’s HTTP invoker .

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 .

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>
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 WEB-INF/remoting-servlet.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>

Ce fichier de configuration dans notre cas est le fichier WEB-INF/remoting-servlet.xml qui est retrouvé par la servlet de nom remoting. Le nom du fichier XML Spring suit la règle de nommage NOM_SERVLET-servlet.xml où NOM_SERVLET est le nom de la servlet définit dans le web.xml via servlet-name.

La définition du bean UserService du fichier WEB-INF/remoting-servlet.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" />
applicationContext.xml

Le bean d’ID userService retourne une instance de la classe org.dynaresume.services.impl.UserServiceImpl :

	<bean id="userService" class="org.dynaresume.services.impl.UserServiceImpl"></bean>

Cette définition pourrait être mise dans le fichier remoting-servlet.xml, mais une bonne pratique est de séparer dans des fichiers XML distincts, les définitions des implémentation des services et les définition des services exportés par HttpInvoker. La définition du bean userService s’effectue dans le fichier XML Spring WEB-INF/applicationContext.xml.

Listener

Ce fichier doit être chargé en définissant un listener Spring org.springframework.web.context.ContextLoaderListener qui doit se déclencher au démarrage de l’application WEB :

<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Il permet de charger le fichier XML Spring WEB-INF/applicationContext.xml qui est indiqué par la propriété contextConfigLocation :

<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

JAR Spring

Copiez les librairies de la distribution Spring DM dans WEB-INF/lib.

Jar Description
lib/com.springsource.org.aopalliance-1.0.0.jar Extensions à spring (Spring Framework)
lib/com.springsource.slf4j.api-1.5.0.jar L’API public de SLF4J
lib/com.springsource.slf4j.log4j-1.5.0.jar L’implémentation de SLF4J qui utilise log4j pour faire le logging
lib/com.springsource.slf4j.org.apache.commons.logging-1.5.0.jar Un remplaçant d’Apache commons-logging (réputé pour ses problèmes liés au classloading) qui utilise SLF4J pour le logging
lib/log4j.osgi-1.2.15-SNAPSHOT.jar La version OSGifié de log4j
lib/org.springframework.aop-2.5.6.A.jar Extensions à spring (Spring Framework)
lib/org.springframework.beans-2.5.6.A.jar Extensions à spring (Spring Framework)
lib/org.springframework.context-2.5.6.A.jar Extensions à spring (Spring Framework)
lib/org.springframework.core-2.5.6.A.jar Extensions à spring (Spring Framework)
lib/org.springframework.web-2.5.6.A.jar Extensions à spring (Spring Framework)
lib/org.springframework.web.servlet-2.5.6.A.jar Extensions à spring (Spring Framework)

Les JARs nécéssaires sont les mêmes que ceux utilisé dans les billets précédants, excepté 2 nouveaux JARs org.springframework.web-2.5.6.A.jar et org.springframework.web.servlet-2.5.6.A.jar qui permettent d’utiliser Spring dans un contexte WEB (contient la servlet DispatcherServlet, le listener ContextLoaderListener…).

web.xml

Modifiez le fichier web.xml pour définir la servlet remoting et le listener qui charge le fichier XML Spring applicationConetxt.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>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	
	<servlet>
		<servlet-name>remoting</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

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

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/applicationContext.xml</param-value>
	</context-param>
	
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
</web-app>

remoting-servlet.xml

Créez le fichier remoting-servlet.xml dans le répertoire WEB-INF 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>

applictionContext.xml

Créez le fichier applictionContext.xml dans le répertoire WEB-INF 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 id="userService" class="org.dynaresume.services.impl.UserServiceImpl"></bean>
</beans>

Log4j

Relancez l’application WEB, la console affiche le warning suivant :

log4j:WARN No appenders could be found for logger (org.apache.catalina.startup.TldConfig).
log4j:WARN Please initialize the log4j system properly.

Ce qui signifie que log4j n’est pas configuré correctement. Créez le fichier log4j.properties dans le répertoire src avec le contenu suivant :

log4j.rootLogger=info, con
log4j.appender.con=org.apache.log4j.ConsoleAppender
log4j.appender.con.layout=org.apache.log4j.PatternLayout
log4j.appender.con.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

Relancez et la trace suivante s’affiche :

...
187 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/applicationContext.xml]
...
437 [main] INFO org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 437 ms
516 [main] INFO org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/dynaresume-server] - Initializing Spring FrameworkServlet 'remoting'
...
531 [main] INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/remoting-servlet.xml]
...
812 [main] INFO org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'remoting': initialization completed in 296 ms

Elle montre que le fichier XML Spring /WEB-INF/applicationContext.xml est chargé correctement ainsi que la servlet remoting.

Test Remoting

A ce stade il est difficile de tester notre service sans client. Le test qu’il est possible d’effectuer est d’ouvrir un navigateur est de tapper l’URL
http://localhost:8080/dynaresume-server/remoting/UserService qui affiche l’erreur suivante :

java.io.EOFException
java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
java.io.ObjectInputStream.readStreamHeader(Unknown Source)
java.io.ObjectInputStream.(Unknown Source)
org.springframework.core.ConfigurableObjectInputStream.(ConfigurableObjectInputStream.java:47)
org.springframework.remoting.rmi.CodebaseAwareObjectInputStream.(CodebaseAwareObjectInputStream.java:81)
org.springframework.remoting.rmi.RemoteInvocationSerializingExporter.createObjectInputStream(RemoteInvocationSerializingExporter.java:105)
org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter.readRemoteInvocation(HttpInvokerServiceExporter.java:115)
org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter.readRemoteInvocation(HttpInvokerServiceExporter.java:96)
org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter.handleRequest(HttpInvokerServiceExporter.java:73)
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:49)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)

Cette trace permet quand même de vérifier que la servlet remoting est bien appelé et qu’elle cherche le service UserService.

Conclusion

Dans ce billet nous avons mis en place Spring Remoting via HttpInvoker dans une application WEB classique. Cette mise en ouvre de Remoting s’effectue déclarativement via le web.xml et des fichiers XML Spring. Dans le prochain billet nous allons mettre en place un client OSGi et sans OSGi qui appelera le service UserService.

L’application WEB permet d’exposer des services par Remoting. Le distribuable d’une application WEB se présente généralement sous forme de WAR ou d’EAR qui peuvent être conséquent. La correction/évolution d’un patch service engendre :

  • une nouvelle construction du WAR/EAR, qui peut être très couteuse si le projet est conséquent.
  • le redémarrage de l’application WEB avec la nouvelle distribution, qui peut être impactant pour les utilisateurs.

Ces problèmes n’existent pas dans un contexte OSGi ou il est possible de livrer un bundle OSGi et de pouvoir l’installer sans arrêter le conteneur OSGi. Nous verrons dans un billet futur comment mettre en place une application WEB dans un bundle OSGi.

Vous pouvez lire le billet suivant [step10].

Catégories :DynaResume, Spring, Spring Remoting Étiquettes :
  1. Hervé
    décembre 19, 2009 à 9:26

    Bonsoir,
    Tout d’abord, je tiens à vous féliciter pour la qualité de votre travail, pour la clarté et la précision des billets. Je débute avec osgi et depuis 1 semaine, je ne quitte pas votre blog. J’attends la suite avec impatience😉

    A propos de ce billet, je me demande néanmoins pourquoi avoir choisi le remoting et HTTP Invoker. Personnellement, j’aurais préféré une version serveur avec des webservices (JAX-WS). Mais peut être est-ce prévu ?

    Encore merci pour vos billets.

    Hervé

    • décembre 19, 2009 à 11:40

      Bonsoir hervé,

      Merci beaucoup pour vous encouragements. Je suis ravi que cela puisse vous aider. Je suis sur le [step11] qui parle de Spring Remoting cote serveur dans un bundle OSGi. Je pense que les prochains billets seront consacrés au client Eclipse RCP (client qui affichera la liste des users dans une Table SWT) et de montrer comment intégrer uen application RCP avec Spring DM. Ensuite je parlerais de la couche DAO (acces données). J’ai donc encore beaucoup de chose à étudier pour ensuite rédiger les billets.

      J’ai choisi le remoting HTTP Invoker car c’est ce que Pascal Leclercq a commencé à mettre en place dans DynaResume. Je decouvre aussi le remoting, mais j’ai l’impression que HTTP Invoker est la plus légère. Ce qui me fait un peu peur avec le remoting « webservices (JAX-WS) », ce sont les performances dans des cas de transfert de gros volumes de données (transfert de gros messages SOAP XML).

      Je n’ai jamais testé les autres types de Remoting mais je pense que le coté déclaratif de Spring permet de changer simplement de Remoting. D’ailleurs le gros interet du decoupage en bundles OSGi et de pouvoir creer d’autres bundles de remoting sans impacter les autres bundles OSGi. Dans le [step10] vous pouvez voir ca pour la partie cliente (bundle org.dyanresume.remoting.importer.http . Pour la partie server ca sera dans le [step11]

      Merci de votre post.

      Angelo

    • décembre 20, 2009 à 11:10

      Bonjour,
      actuellement nous nous limitons à l’export de services en remoting http car c’était le plus immédiat. les problématiques de transports sont isolées dans des bundles bundles « *.http.exporter » et « *.http.importer ». Changer de solution de transport reviens à remplacer ces bundles.
      D’autres solutions de transports seront étudiés par la suite notamment :
      – ECF
      – r-OSGi (http://cxf.apache.org/distributed-osgi.html)

      Je ne suis pas en mesure de fournir un délai, toutefois cette tâche ne faisait pas partie de mes priorités pour la première itération.

      Il est toutefois possible (et souhaité) de saisir des évolutions souhaitées à cette adresse : http://code.google.com/p/dynaresume/issues/list
      Cordialement

    • jawher
      décembre 20, 2009 à 12:08

      Bonjour,
      Etant membre du projet Dynaresumé, je me permet de répondre à ta question à propos du remoting.

      On avait pas encore mis sur table quel techno utiliser pour le remoting. Pascal a utilisé le HttpInvoker de Spring, et il se trouve que moi uassi j’utilise cette même technique dans mes projets OSGI au boulot).

      J’avais commencé avec Hessian (via Spring) que je trouve plus rapide et plus léger que HttpInvoker, mais avec le temps, mes entotiés étaient devenues de plus en plus complexes et Hessian n’arrivait plus à suivre (des exceptions bizarres lors de leur sérialisation/désérialisation).

      Le HttpInvoker de Spring présente un juste milieu : il est parfaitement intégré à Spring (of course), il utilise la sérialisation Java donc il arrive à gérer n’importe quel niveau de complexité des entités. Enfin, il utilise HTTP, donc passerait moins douleureusement sur diverses installations réseaux/firewalls.

      Jusque là, toutes ces alternatives sont des technos centrés Java. Leur mise en place est des plus faciles et simples, donc idéaux pour commencer avec.

      Mais il est clair que si on veut supporter d’autres clients non java (xul, flex, etc.), il faudrait exposer nos services en utilisant un autre moyen non spécifique à Java. Et justement, avec OSGi et une bonne conception, on pourra exposer les mêmes services via différents moyens et façon dynamiques (du genre ajouter un bundle permettrait d’exposer tels services avec amf3, sans avoir à recompiler)

      Les webservices sont une alternative. Personellement, je suis pas très chaud à leur utilisation. Je les déteste même (je sais que je devrais pas). Je trouve qu’ils sont trop lourd à mettre en place et qu’ils cherchent à résoudre beacoup trop de problèmes de sorte que gérer un cas simple devient complexe. Les WSDL automatiquement générés sont horribles et très sensible à tout changement dans le backend. Mais bon, ce n’est que mon point de vue personnel et ça n’engage pas DynaRésumé.

      Par contre, REST est une bonne laternative amha, qui est à la fois simple à mettre en place, propre à coder et neutre côté technologies.

  2. Stevens
    avril 12, 2010 à 10:19

    Bonsoir à tous,

    je voudrais préciser que dans une bonne conception de développement par service, le service en lui même ne doit pas être lié à l’OSGI. Tout comme les connecteurs, le service OSGI est un projet à part entière.

    L’HttpInvoker permet de faire des accès distants au service, le module OSGI des accès locaux.

    Cela permet de créer de nouveaux connecteurs à volonté, suivant les besoins.

    Pour ma part, j’utilise HttpInvoker pour accéder à plusieurs serveurs Tomcat et faire de la répartition de charge. Tomcat n’est pas installé en cluster ce qui simplifie grandement la problématique d’ajout de noeud ou de suppression de noeud (merci JGroup).

    Je confirme également que les posts sont de qualité. Bravo Angelo!

    • avril 13, 2010 à 12:37

      Bonjour Stevens,

      >L’HttpInvoker permet de faire des accès distants au service, le module OSGI des >accès locaux.

      La je ne suis pas tout a fait d’accord car ECF propose de faire du remoting via le service de registres OSGi => http://wiki.eclipse.org/Distributed_OSGi_Services_with_ECF

      Maintenant il est vrai que le client doit supporter OSGi pour beneficier de ECF. Pour les applications Eclipse RCP, c’est le cas.

      Concernant le remoting, nous avons découpé comme l’a expliqué Pascal en bundle OSGi « *.http.exporter » (cote serveur) et « *.http.importer » (cote client), donc il est possible de creer un nouveau type de remoting (ex ECF).

      J’ai développé un support Spring pour ECF, qui permet de déclarer (comme httpInvoker) le remoting des services pour ECF via des bean Spring. Pour plus d’informations, voir
      http://wiki.eclipse.org/Using_Spring_with_ECF_Remote_Services

      > Je confirme également que les posts sont de qualité. Bravo Angelo!
      Merci de tes encouragements, ca fait bien plaisir.

      Angelo

  3. Arnaud Cogoluègnes
    mai 1, 2010 à 5:32

    Pour répondre (un peu tard) à la question de Hervé concernant le choix entre une solution de remoting et des Web Services type SOAP, le critère le plus important à considérer est le couplage entre le serveur et le client.
    Avec une solution de remoting type HTTP Invoker, le serveur et le client sont fortement couplés, non seulement via la technologie mais aussi via la nécessité de tout connaître du service qu’on appelle (nom de la méthode, arguments, type de la réponse). Bref, il faut que le JAR de l’interface du service soit à la fois chez le client et sur le serveur. Une telle solution est adaptée quand on veut faire simple et que l’on maîtrise complètement les clients et le serveur. C’est une bonne solution pour de la communication entre des clients de type application de bureau (Swing, Eclipse RCP) et des serveurs web. En plus, comme on passe par de la sérialisation Java, c’est rapide.
    Une solution type web services SOAP (ou REST) est plus adaptée si on veut un couplage lâche entre clients et serveur. On définit un contrat de communication (WSDL pour SOAP, WADL pour REST) et chaque parti doit bien le respecter pour communiquer. Ce contrat doit rester stable dans la mesure du possible. C’est une solution adaptée quand on ne contrôle pas les clients qui peuvent accéder aux services.

  1. décembre 15, 2009 à 9:54
  2. décembre 22, 2009 à 2:26
  3. décembre 24, 2009 à 8:55

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 :