décembre
2008
Suite à ce billet : Vos premiers pas avec SpringSource Application Platform et eclipse où j’avais montré comment configurer le tooling STS avec Eclipse ainsi que la création et le déploiement d’une application exemple, je vais montrer dans ce billet comment développer une application multi-tiers s’étalant sur plusieurs bundles.
1. Vue d’ensemble
L’application que je vais utiliser comme exemple est simpliste : elle ne sert qu’à afficher une liste de personnes (peu importe comment cette liste est retrouvée) dans une page web.
Seulement, histoire de faire propre, je vais découper cette application en 4 bundles:
- domain: C’est un bundle qui définit les objets métier (un seul dans notre cas: Person)
- service-api: C’est un bundle qui définit les interfaces (contrats) de la couche métier
- service-impl: C’est un bundle qui définit les implémentations des services mais aussi les exporte en tant que services OSGi qui seront consommés par le dernier bundle.
- web-frontend: C’est un bundle qui définit le front-end web de l’application et qui consomme les services exposés par service-impl
N.B.: Je suppose tout au long de ce billet que le serveur S2AP ainsi que le tooling Eclipse correspondant est déjà en place comme je le montre ici.
2. Créer le bundle domain
Dans Eclipse, lancez le wizard « New Bundle Project » :
Saisissez un nom parlant pour ce bundle (djo.s2ap.demo.domain pour moi) et cliquez sur Next.
Là, et c’est une nouveauté dans le tooling S2AP pour Eclipse (sur une suggestion de ma part, merci à Christian Dupuis qui l’a implémenté), il est possible de choisir le type du bundle (None ou Web) :
Choissisez None et validez.
Créer un package dans le dossier src (j’utilise habituellement le nom du projet comme package de base), et créez une classe Person (forcément, mon type de données préféré )
package djo.s2ap.demo.domain;
public class Person {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Je vais me contenter de cette classe comme mon domaine.
Il faut ensuite exporter le package de cette classe pour qu’elle soit visible aux autres bundles.
Pour ce faire, localisez le fichier src/META-INF/MANIFEST.MF et double-cliquez la dessus, ce qui ouvre l’éditeur de manifest de STS (encore une fonctionnalité proposé par l’auteur de ce billet (moi) et implémentée par l’equipe STS (re-merci) !).
Dans l’éditeur multi-pages qui se lance, localisez la page « Runtime » et activer la.
A gauche, vous trouverez une liste présentant les packages exportés par le bundle en question. Cliquez sur le bouton « Add » et dans la fenêtre qui s’affiche, sélectionnez l’unique package présent (djo.s2ap.demo.domain).
Sinon, il est toujours possible de travailler directement sur le manifest en utilisant le contenu suivant:
Manifest-Version: 1.0
Bundle-Version: 1.0.0
Bundle-Name: Domain Bundle
Bundle-ManifestVersion: 2
Bundle-SymbolicName: djo.s2ap.demo.domain
Export-Package: djo.s2ap.demo.domain
Voilà, le premier bundle est prêt.
3. Créer le bundle service-api
Comme énoncé plus haut, ce bundle va juste définir les contrats des services (sous forme d’interfaces). C’est LE pattern OSGi à mon avis, i.e. séparer l’interface de l’implémentation dans des bundles différents, histoire de pouvoir changer (mettre à jour, corriger des bugs, peaufiner, etc.) l’implémentation séparément de son interface mais aussi pour éviter que le consommateur d’un service ne dépende de son implémentation.
Dans le cadre de cette application exemple, je vais me contenter d’un seul service exposant une seule fonctionnalité qui est de récupérer une liste de personnes.
Commencez par créer un autre bundle nommé « djo.s2ap.demo.service.api » dans mon cas (même procédure que pour le bundle domain, choisissez « None » comme personality).
Ce bundle aura besoin de voir la classe Person du bundle domain.
Or, justement, j’ai exporté le package contenant cette classe. Il ne reste plus qu’à importer ce package dans le bundle service.api.
Pour ce faire, localisez et double-cliquez sur le fichier « src/META-INF/MANIFEST.MF » du bundle service.api.
Dans l’éditeur multi-pages qui s’affiche, activez la page « Dependencies ».
Dans la liste à gauche (Import Package », cliquez sur Add, et localisez le package « djo.s2ap.demo.domain » contenant la classe Person (utilisez le filtre):
Sélectionnez ce package et validez.
Ainsi, la classe Person devient visible dans le second bundle.
Créez ensuite un package « djo.s2ap.demo.service.api » avec une interface IPersonRepository dont voici le code:
package djo.s2ap.demo.service.api;
import java.util.List;
import djo.s2ap.demo.domain.Person;
public interface IPersonRepository {
List<Person> getPersonsList();
}
Pour finir, il faut exporter le package qui définit cette interface car l’implémentation de ce service aura besoin d’y accéder.
Donc, comme montré plus haut, exportez le package « djo.s2ap.demo.service.api » en utilisant soit l’editeur graphique du manifest ou en jouant directement sur le manifest.
4. to be continued
Faute d’espace et de temps, je vais m’arrêter là pour ce billet et je finirais la chose bientôt dans un autre billet.
Toujours faute de temps, mais aussi à cause du fait que j’ai abandonné S2DMS, j’arrive pas à finir le second volet
J’espère au moins pouvoir parler des raisons du pourquoi j’ai abandonné cette plateforme (1 raison plus précisément, la notion de PAR)
Voici une première piste pour t’aider :
http://static.springsource.com/projects/s2ap/1.0.0.beta/programmer-guide/html/ch08.html
Quoi ? 1600 mots, je me suis même pas rendu compte …
ça se boit comme du ptit lait, euh pardon, du java.
benwitt> mais nooon … j’avais l’intention de tout montrer dans ce billet, seulement ça m’a pris énormément de temps : je suis ladessus depuis lundi, et le billet a atteint une taille inhumaine (1600 mots et j’étais presque à la moitié). J’ai donc décidé de poster ce qui était fait dans un billet et de continuer de travailler sur le reste dans un autre billet.
Hikage> ouch … j’ai pas encore testé celà, et je suis effrayé rien qu’en y pensant: OSGi et les manips bas-niveau d’Hibernate (proxying, reflection, etc.) ça risque de faire mal !
Bon je vote pour une implémentation du service basé sur Hibernate :p
oh, le beau « Cliffhanger » qui va nous tenir en haleine jusqu’au prochain épisode !!!