juin
2008
Voilà, tout est dans le titre: je suis enfin arrivé à créer et à deployer mon premier bundle (et non pas war) utilisant Wicket sur SpringSource Application Platform (S2AP), chose qui était non faisable jusqu’à la beta 5 de S2AP qui apporte la pièce manquante: les fragments web.xml.
SpringSource voulait initialement fournir une nouvelle méthode pour la configuration d’une application web, qui utilise le manifest au lieu de l’habituel web.xml.
Seulement, dans les premières versions (et même jusqu’à la plus récente), les paramètres de configuration étaient limités comparé à ceux offerts par web.xml, ce qui a fait que plusieurs frameworks webs ne pouvaient pas être utilisés dans un bundle web de S2AP.
Pour Wicket, ce qui manquait avant, c’était:
- La possibilité de déclarer une servlet/filtre dans le manifest des bundles. Ce point a été adressé (quoi que partiellement) en donnant la possibilité de spécifer des servlets dans le manifest (mais pas les filtres, utilisés par Wicket depuis la version 1.3).
- Mais surtout la possibilité de spécifier les init-params des servlets/filtres depuis le manifest.
- enfin, les méta-données OSGi dans la distribution wicket.
S2AP beta 5 a donc résolu les deux premiers points en donnant la possibilité d’utiliser le bon vieux web.xml dans les bundles, ce qui nous permet donc de déclarer le filtre de Wicket, son mapping ainsi que l’init-param « applicationClassName« .
Le dernier point a lui été adressé par l’équipe de Wicket qui ont inclus ledits méta-données OSGi dans les manifest des jars de Wicket 1.4 (disponible actuellement en version « Milestone 2« ).
Bon, en réalité, il y’avaient quelques problèmes dans ces méta-données comme ici par exemple ou encore ici, mais l’équipe Wicket est suffisamment réactive et rapide pour que ces détails soient réglées en quelques jours.
remarque aussi que l’équipe de S2AP est en train d’OSGi’fier la distribution actuelle de Wicket (1.3.3) (suivi ici).
Voici maintenant comment créer un bundle Wicket-powered:
Serveur
Assurez vous que vous avez S2AP beta 5 qui soit installée sur votre disque (« /home/djo/Java/servers/springsource-ap-1.0.0.beta5/ » dans mon cas).
Installer les jars OSGi’fiés de Wicket
Téléchargez ensuite la distribtion Wicket 1.4 M2 (téléchargeable ici) et décompressez la. Copiez le fichier « wicket-1.4-m2.jar » du dossier lib vers le dossier « repository/bundles/usr » de S2AP (« /home/djo/Java/servers/springsource-ap-1.0.0.beta5/repository/bundles/usr » dans mon cas).
Installer les jars OSGi’fiés de SLF4J (enfin presque)
Il nous faut aussi Slf4j, donc, normalement, il faut se rendre dans le respository de SpringSource pour récupérer les jars OSGI’fiés de Slf4j et « Slf4j log4j binding » et les copier dans le dossier « repository/bundles/usr« , mais je vais montrer une autre façon beaucoup plus pratique pour le faire.
Installer le tooling eclipse
Dans eclipse, assurez vous que le tooling de SpringSource (ainsi que Spring IDE) est mis en place comme montré ici.
Installer les jars OSGi’fiés de SLF4J (pour de vrai)
Dans la vue Servers, double cliquez sur le serveur S2AP et dans la fenêtre qui s’affiche, activer l’onglet repository.
Cette vue (éditeur en fait) permet de rechercher et récupérer des jars depuis le repository S2, le tout depuis eclipse.
Effectuez une recherche sur slf4j, cochez SLF4J API et SLF4J LOG4J Binding et cliquez sur download => Et hop, ils seront ajoutés dans le repository de S2AP.
Le manifest
Créez un nouveau bundle (nommé « djo.s2ap.wicket » dans mon cas) et modifiez son manifest comme ceci:
Manifest-Version: 1.0
Bundle-Version: 1.0.0
Bundle-Name: Wick Bundle
Bundle-ManifestVersion: 2
Web-ContextPath: wicket
Bundle-SymbolicName: djo.s2ap.wicket
Platform-ModuleType: Web
Import-Package:
org.apache.wicket,
org.apache.wicket.markup.html,
org.apache.wicket.markup.html.basic,
org.apache.wicket.model,
org.apache.wicket.protocol.http,
org.apache.wicket.behavior,
org.apache.wicket.ajax,
org.apache.wicket.util.time,
org.slf4j
Le fragment de web.xml
Créez ensuite un dossier WEB-INF dans le dossier src du bundle, et un fichier web.xml ladedans avec ce contenu:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>wicket</display-name>
<filter>
<filter-name>WicketApplication</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>djo.s2ap.wicket.MyApp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>WicketApplication</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
L’infrastructure Wicket
Créez un package « djo.s2ap.wicket ». dans ce package, on crée comme d’habitude pour Wicket une classe pour l’application, une classe et une page html pour la page d’accueil.
Classe de la page d’accueil
package djo.s2ap.wicket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.util.time.Duration;
public class MainPage extends WebPage<MainPage> {
private static final DateFormat df = new SimpleDateFormat("HH:mm:ss");
public MainPage() {
final Label<String> currentTime = new Label<String>("time",
new LoadableDetachableModel<String>() {
@Override
protected String load() {
return df.format(new Date());
}
});
currentTime.add(new AjaxSelfUpdatingTimerBehavior(Duration.ONE_SECOND));
add(currentTime);
}
}
Page HTML de la page d’accueil (MainPage.html)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Test</title>
</head>
<body>
<span wicket:id="time">...</span>
</body>
</html>
Classe de l’application
package djo.s2ap.wicket;
import org.apache.wicket.protocol.http.WebApplication;
public class MyApp extends WebApplication {
@Override
public Class getHomePage() {
return MainPage.class;
}
}
Déploiement et test
Et voilà : reste plus qu’à deployer et tester la chose.
En ce qui me concerne, j’arrive pas à lancer un bundle depuis eclipse, donc je procède manuellement en exportant le projet du bundle en jar (via le wizard standard d’eclipse). Il faut juste faire attention à utiliser le manifest du projet comme manifest du jar.
Je place ensuite le jar généré dans le dossier pickup de s2AP (/home/djo/Java/servers/springsource-ap-1.0.0.beta5/pickup) et je démarres le serveur (depuis eclipse ou via bin/startup.sh).
Tapez ensuite l’adresse suivante dans le navigateur:
http://localhost:8080/wicket/
et hop, j’ai une page qui affiche le temps courant en temps réel (enfin presque, rafraichissement ajax chaque seconde).
Sources
Le jar en question (ainsi que les sources) peuvent être téléchargées ici.
TODO
Dans un futur billet, je vais montrer comment utiliser Spring avec Wicket pour retrouver un service OSGi exporté par un autre bundle.
Pas encore.
Est-ce que ce bille a été rédigé entre temps ?
Youre ouelcome !
Pur les Import-bundle, j’essaies autant que possible de ne pas trop s’éloigner du vanilla-osgi en utilisant uniquement les Import-Package … mais c’est néanmoins une excellente idée en effet !
Génial ! Je vais pouvoir tester ça ce soir.
Merci de faire partager.
Petite question cependant : pourquoi tu ne fais pas tout simplement un « Import-Bundle » plutôt que tout un tas de « Import-Package » ?
Import-Bundle:
org.apache.wicket;version= »… »,
com.springsource.slf4j.api;version= »1.5.0″