|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: XWiki au banc de test |
| 4 | +author: feugy |
| 5 | +tags: [xwiki, groovy, velocity, wiki, CMS, smartdata] |
| 6 | +published: false |
| 7 | +--- |
| 8 | + |
| 9 | +Il existe plétorde de produits pour faire un Wiki, tous plus complets les uns que les autres. |
| 10 | +Alors en quoi XWiki se démarque-t-il ? |
| 11 | + |
| 12 | +> XWiki, c'est bien plus qu'un wiki. (~~vous voila convaincus, non ?) |
| 13 | +
|
| 14 | +C'est en effet ce qui est cranement annoncé sur le site [xwiki.org](http://www.xwiki.org/xwiki/bin/view/Main/WebHome) sous l'appellation ["Wiki de seconde génération"](http://platform.xwiki.org/xwiki/bin/view/Main/SecondGenerationWiki). |
| 15 | +Alors, qu'il y a t'il derrière ce discours commercial ? |
| 16 | +La promesse d'un véritable couteau-suisse du Web ? |
| 17 | +Ou un n-ième et décevant CMS ? |
| 18 | + |
| 19 | + |
| 20 | +## Cas d'étude |
| 21 | + |
| 22 | +Pour les besoin d'une démonstration, j'ai du mettre en place un portail Web minimaliste incluant les fonctionnalités suivantes : |
| 23 | + |
| 24 | +* une page d'accueil |
| 25 | +* un espace de partage de données publiques (nous allons y revenir) |
| 26 | +* un blog sans workflow de validation (brouillon > publié) |
| 27 | +* un Forum simpliste (pas de message privés) |
| 28 | + |
| 29 | +Le tout en 2 semaines, mise en prod inclue. |
| 30 | + |
| 31 | +L'occasion révée de tester XWiki, régulièrement promu par Vincent Massol dans son podcast [les cast codeurs](http://lescastcodeurs.com/), |
| 32 | +et qui propose 3 des 2 fonctionnalités (le forum est un "plugin" nommé [Bulletin board](http://extensions.xwiki.org/xwiki/bin/view/Extension/Bulletin+Board+Application)) |
| 33 | + |
| 34 | +XWiki est écrit en Java, et utilise Spring, Hibernate/JPA, Struts, et Velocity. Il est personnalisable avec Groovy, Python, Ruby ou encore Php. |
| 35 | + |
| 36 | + |
| 37 | +## Qu'est ce qu'un Wiki 2ème génération ? |
| 38 | + |
| 39 | +Alors si j'ai bien tout compris (à vous de vérifier donc :)), le Wiki de 2ème génération est un [CMS](http://fr.wikipedia.org/wiki/Syst%C3%A8me_de_gestion_de_contenu). |
| 40 | + |
| 41 | +XWiki (en version 3.2) propose effet tout ce qui caractérise un CMS : |
| 42 | + |
| 43 | +* un portail Web qui présente du contenu éditorial, produit par plusieurs utilisateurs |
| 44 | +* une séparation entre les données (contenues dans Classes et de Objets) et leur présentation (utilisation de Velocity comme moteur de templating, et de CSS) |
| 45 | +* une structuration du contenu : hiérarchisation, organisation en espaces plus ou moins spécialisé (espace forum, espace blog...) |
| 46 | +* une véritable gestion des comptes utilisateur et de leurs permissions sur l'ensemble des objets |
| 47 | +* un versionning du contenu |
| 48 | + |
| 49 | +En revanche, pas de workflow de publication, bien qu'il soit tout a fait possible d'en créer un. |
| 50 | + |
| 51 | +Car ce qui différentie XWiki des autres produits de Wiki et CMS, c'est son extrème flexibilité. |
| 52 | +Il est important de distinguer plusieurs rôles dans la population des utilisateur : l'utilisateur final (l'internaute), l'utilisateur privilégié (le webmaster), le développeur (qui cré des composants/plugins). |
| 53 | +Du point de vue des utilisateurs privilégiés, XWiki n'est pas particulièrement facile à prendre en main. Il est en revanche [très bien documenté](http://enterprise.xwiki.org/xwiki/bin/view/UserGuide/WebHome) |
| 54 | +Pour les développeurs c'est l'inverse : très mal documenté, et extèmement puissant. |
| 55 | + |
| 56 | + |
| 57 | +## Le modèle de donnée XWiki |
| 58 | + |
| 59 | +Dans XWiki, tout est "document". Héritage naturel du Wiki. |
| 60 | +Un document dispose à minima d'un nom unique (utilisé comme url), et d'un certain nombre de propriétés (clé-valeur typée String, nombre, date...). |
| 61 | +Ces propriétés sont définis dans une <tt>Classe</tt>, et les documents sont donc des <tt>Objets</tt>, instances de ces classe. |
| 62 | + |
| 63 | +En gros, si je veux définir un billet de blog, je crée une classe Blog avec 3 champs (auteur, contenu, date de publication), et pour chaque billet le système crée un <tt>Objet</tt> ayant son url propre (<tt>/xwiki/bin/view/Blog/Mon+nom+de+billet</tt>). |
| 64 | + |
| 65 | +Sur chaque document, XWiki propose les actions suivantes : |
| 66 | + |
| 67 | +* <tt>edit</tt>: création/mise à jour du document |
| 68 | +* <tt>view</tt>: visualisation |
| 69 | +* <tt>delete</tt>: suppression |
| 70 | + |
| 71 | +Au niveau rendu, il est possible d'attacher à la classe un "Class Template" : c'est le formulaire qui permet de remplir les propriétés d'un document lors de l'action <tt>edit</tt>. |
| 72 | +On peux aussi attacher une "Class Sheet" : template Velocity pour le rendu (action <tt>view</tt>) des <tt>Objets</tt>. |
| 73 | + |
| 74 | + |
| 75 | +## Premier pas en temps que développeur. |
| 76 | + |
| 77 | +Très facile à installer (un war à déposer dans un conteneur Servlet), XWiki propose ensuite des fonctionnalités d'import/export, et de personnalisation en ligne. |
| 78 | + |
| 79 | +Ainsi, avec le compte administrateur, et directement dans l'application, on crée et modifie <tt>Classes</tt> et <tt>Objets</tt>. |
| 80 | +Le moteur de template [Velocity](http://velocity.apache.org/) est très facile à prendre en main, et j'ai choisis Groovy pour la "logique applicative" à l'intérieur des pages. [Groovy](http://groovy.codehaus.org/) apporte toute la puissance d'un language dynamique à la plateforme Java, tirant partie des librairies existantes, |
| 81 | + |
| 82 | +Tout ce passe donc à chaud, sans redémarrage. |
| 83 | +Très pratique. Par contre, on édite du code dans un textarea : aucune fonctionnalité d'IDE. |
| 84 | +Il existe cependant un plugin Eclipse pour combler ce manque. |
| 85 | + |
| 86 | +Coté versionning, chaque sauvegarde provoque une nouvelle version de l'<tt>Object</tt>, la <tt>Classe</tt>, le <tt>Class Template</tt> ou la <tt>Class Sheet</tt>. Donc possible de revenir en arrière lorsqu'on à cassé quelque chose. |
| 87 | + |
| 88 | +La fonction d'export permet de faire un zip avec les modifications et configuration qu'on a apporté à son instance. Et naturellement, la fonction d'import permet de "déployer" son zip sur une autre instance. |
| 89 | + |
| 90 | + |
| 91 | +## Le développement spécifique |
| 92 | + |
| 93 | +XWiki promet une grande facilité d'extension, permettant au développeur d'enrichir les fonctionnalités de base pour "spécialiser" le produit pour un besoin fonctionnel donné. |
| 94 | + |
| 95 | +Dans mon cas, je devais proposer à l'intérieur du portail les fonctionnalités de collecte et partage de données publiques. Le service sous-jacent est Smart Data, accessible via une API Http. |
| 96 | +Pour résumer : |
| 97 | +* Une page pour uploader un fichier de données, et donner nom/description de la source de données |
| 98 | +* Une page pour afficher et réaliser une recherche sur les sources de données existantes. |
| 99 | +* Une page pour visualiser le contenu d'une source de données (et télécharger le fichier original) |
| 100 | +* Une page pour supprimer les sources de données. |
| 101 | + |
| 102 | +A chaque fonctionnalité correspond une API du service Web de Smart Data. |
| 103 | + |
| 104 | +Première solution : créer une Classe "DataSource", et avoir un Objet "DataSource" pour chaque source de données. Toute la logique de médiation est embarquée dans les page. |
| 105 | + |
| 106 | +Deuxième solution : créer un "composant" XWiki : des classes Java pour enrichir le fonctionnel XWiki, et encapsuler la logique de médiation un peu mieux que dans les pages. Les fonctionnalités sont ensuite accessible dans les pages sous forme de "macro". |
| 107 | + |
| 108 | +J'ai pris la seconde solution, car elle me semblait plus "propre": meilleur découpage/découplage de ma logique propre à Smart Data, meilleur testabilité. |
| 109 | + |
| 110 | +Ex: l'Object XWiki ViewDataSource (template Velocity) |
| 111 | +{% highlight html %} |
| 112 | +{{velocity}} |
| 113 | +{{html wiki="true"}} |
| 114 | +## Appel au composant maison : invoque la méthode get() pour récupérer le datasource sur Smart Data. |
| 115 | +#set($dataSource = $services.distantDataSourceService.get($request.getParameter('id'))) |
| 116 | + |
| 117 | +<div class="sd-datasource"> |
| 118 | + <div class="sd-title"> |
| 119 | + ## Utilisation de l'objet renvoyé : |
| 120 | + <span class="sd-title">${dataSource.name}</span> |
| 121 | + </div> |
| 122 | + <div class="sd-content sd-tags"> |
| 123 | + #foreach($tag in $dataSource.tags) |
| 124 | + <span class="sd-value sd-tag">$tag</span> |
| 125 | + #end |
| 126 | + </div> |
| 127 | + <div class="sd-content sd-description"> |
| 128 | + <span class="sd-label">$msg.get('sd.labels.desc')</span> |
| 129 | + <span class="sd-value">$!{dataSource.desc}</span> |
| 130 | + </div> |
| 131 | +</div> |
| 132 | + |
| 133 | +{{/html}} |
| 134 | +{{/velocity}} |
| 135 | +{% endhighlight %} |
| 136 | + |
| 137 | +Ex: l'interface DataSourceService (Groovy) |
| 138 | +{% highlight java %} |
| 139 | +import org.xwiki.component.annotation.ComponentRole; |
| 140 | + |
| 141 | +@ComponentRole |
| 142 | +interface DataSourceService { |
| 143 | + def get(id) |
| 144 | +} |
| 145 | +{% endhighlight %} |
| 146 | + |
| 147 | +Ex: l'implémentation DistantDataSourceService (Groovy) |
| 148 | +{% highlight java %} |
| 149 | +import javax.inject.Named |
| 150 | +import javax.inject.Singleton |
| 151 | +import org.xwiki.component.annotation.Component |
| 152 | +import org.xwiki.component.phase.Initializable |
| 153 | + |
| 154 | +@Singleton |
| 155 | +@Component |
| 156 | +@Named('distantDataSourceService') |
| 157 | +class DistantDataSourceService implements DataSourceService, ScriptService { |
| 158 | + |
| 159 | + def get(def id) { |
| 160 | + def retrieved = null |
| 161 | + // Retrieve the DataSource |
| 162 | + http.request(GET, JSON) { req -> |
| 163 | + uri.path = "api/datasources/$id" |
| 164 | + response.success = { resp, json -> |
| 165 | + retrieved = json |
| 166 | + } |
| 167 | + response.'500' = { |
| 168 | + retrieved = null |
| 169 | + } |
| 170 | + response.failure = { resp, json -> |
| 171 | + throw new Exception("Unable to retrieved DataSource (id $id) ${json.errors}"); |
| 172 | + } |
| 173 | + } |
| 174 | + return retrieved; |
| 175 | + } |
| 176 | +{% endhighlight %} |
| 177 | + |
| 178 | +Le système est assez simple : le composant déclare un certain nombre de services (avec les annotations de la JSR-330), ainsi que les implémentations correspondantes. Ces service sont utilisable directement depuis les Object XWiki (injection de dépendance Spring). |
| 179 | + |
| 180 | + |
| 181 | +## Conclusion : bien ou quoi ? |
| 182 | + |
| 183 | +XWiki se veux comme un outil très flexible et très puissant, une plateforme pouvant supporter le développement de n'importe quel portail Web, quelque soit ses fonctionnalités. C'est pour le moins ambitieux. |
| 184 | + |
| 185 | +Après avoir travaillé deux semaines avec, je suis assez tenté de dire que le pari est réussi. |
| 186 | + |
| 187 | +Pour un développeur, la courbe d'apprentissage est minimale lorsqu'on connait Spring/Hibernate. Le modèle de donnée est simple à prendre en main. Velocity et Groovy également. Pour moi, l'aggrégation de ces technologies est naturelle et à propos. |
| 188 | + |
| 189 | +Maintenant, si j'ai pu atteindre mon objectif, ce ne fut pas sans grincements de dents. Et c'est principalement dû à la flexibilité de l'outil : il y a toujours 2 ou 3 manières de réaliser la même fonctionnalité, et parfois, on s'y perd un peu. |
| 190 | + |
| 191 | +La documentation développeur est un gros point faible à mon sens. |
| 192 | +Enfin, les performances ne sont vraiment pas au niveau. Le temps de chargement d'une page est rédhibitoire pour un site à très fort traffic. |
| 193 | + |
| 194 | +En conclusion, je suis assez conquis par XWiki, mais pas dans une optique "grosse production de gros site à gros traffic". Etre productif en solo est facile, mais je ne suis pas aussi confiant dans le cadre d'une équipe d'une dizaine de personnes. |
| 195 | +Si je peux donc emettre un conseil : essayez le ! |
0 commit comments