I. Introduction▲
Cet article va vous apprendre à utiliser le WadRobotFramework (WRF) pour créer des robots destinés à Google Wave avec un minimum d'efforts.
Il n'a pas pour vocation d'expliquer l'utilisation de Google Wave.
WRF vous permettra d'écrire un robot simple en moins de cinq minutes.
II. Des robots pour Google Wave ?▲
Google Wave est un système de collaboration permettant une communication instantanée entre les participants. Ces participants pouvant être humains ou non.
Dans ce dernier cas, l'on nomme robots des programmes exécutés côté serveur, qui peuvent réagir à différents évènements d'une conversation.
Google fournit une API pour écrire des robots en Java (et en Python).
Un robot est un sous-ensemble d'une application Web, répondant à une URL établie.
Le mois de mars 2010 a vu arriver la v2 de l'API Java. Wave étant toujours un outil récent, son API n'est pas figée et susceptible de changements d'importance. Le WadRobotFramework est compatible avec cette nouvelle API. Les deux versions de l'API Robots de Google cohabiteront jusqu'au 30 juin 2010. Après cette date, seule la v2 sera utilisable en ligne.
III. Google Wave ?▲
Pour décrire Wave à l'emporte-pièce, disons que c'est un grand forum mondial qui possède des fonctionnalités proches de la messagerie instantanée et de la messagerie classique (e-mail). De ce fait, ce mélange novateur possède son propre vocabulaire.
La Wave, c'est le forum, chaque fil (thread) est nommé wavelet, et se compose de blips. Chaque wavelet possède un ou plusieurs participants, ce sont soit des humains soit des robots.
Incroyablement novateur non ? A première vue, non, mais notons pour ultérieurement la possibilité d'ajouter des gadgets dans une conversation, ce qui ouvre un large panorama de possibilités.
IV. Pré-requis▲
Les pré requis pour pouvoir utiliser le WRF sont les mêmes que ceux pour l'API de Google.
- Avoir accès à Google Wave (Depuis la conférence Google IO, GW est ouvert à tous sur inscription)
- Avoir un compte développeur sur App Engine Java
- Pouvoir y créer une application
- Disposer d'Eclipse et du plugin Google
- Télécharger l'API Google
Lors de Google I/O 2010, outre l'ouverture à tous et l'intégration à l'offre Google Apps Entreprise, il a été annoncé que désormais, les robots pour GW pourraient être hébergés en dehors de Google App Engine (GAE). Dans cet article, ce ne sera pas le cas.
V. Robots - la méthode Google▲
La méthode pour écrire des robots est extrêmement bien décrite dans le tutoriel publié à cette adresse
http://code.google.com/intl/fr-FR/apis/wave/extensions/robots/java-tutorial.html
V-A. Exemple de code standard▲
Ci-dessous le code d'un robot minimal possédant deux fonctions:
- dire qu'il est vivant (I'm alive) lorsqu'il est ajouté à une conversation.
- saluer tous les participants (Hi, everybody!)lorsqu'un participant est ajouté
package
parroty;
import
com.google.wave.api.*;
import
com.google.wave.api.event.*;
public
class
ParrotyServlet extends
AbstractRobot {
@Override
protected
String getRobotName
(
) {
return
"Parroty"
;
}
@Override
protected
String getRobotAvatarUrl
(
) {
return
"http://code.google.com/apis/wave/extensions/robots/images/robot_avatar.png"
;
}
@Override
protected
String getRobotProfilePageUrl
(
) {
return
"http://code.google.com/apis/wave/extensions/robots/java-tutorial.html"
;
}
@Override
public
void
onWaveletSelfAdded
(
WaveletSelfAddedEvent event) {
Blip blip =
event.getWavelet
(
).reply
(
"
\n
Hi everybody!"
);
}
@Override
public
void
onWaveletParticipantsChanged
(
WaveletParticipantsChangedEvent event) {
for
(
String newParticipant: event.getParticipantsAdded
(
)) {
Blip blip =
event.getWavelet
(
).reply
(
"
\n
Hi : "
+
newParticipant);
}
}
}
Rien de très compliqué en apparence. En partie parce que cela s'est grandement simplifié par rapport à la v1 de l'API.
Ce code n'est pas des plus excitant pour vos neurones, mais... il y a encore moins excitant.
Pour que ce code soit exécuté lorsque vous ajoutez un robot à une conversation, il faudra au préalable :
- avoir un environnement de programmation prêt
- récupérer le Jar de l'API des robots et ses dépendances (Json)
- déclarer la servlet avec son path spécifiques à respecter (web.xml)
- écrire le fichier de déploiement (appengine-web.xml)
- écrire le code "métier"
- configurer le projet sous Eclipse (classpath)
Sachez qu'avec la v1, il y avait plusieurs étapes supplémentaires.
Bien entendu, du copier-coller à partir des tutoriels fait l'affaire techniquement, mais cela apporte une faible satisfaction.
De plus, c'est à répéter pour chaque nouveau robot.
Heureusement, le WadRobotFramework est là !
Voici un exemple de code WRF
import
org.wadael.waverobotfrmwrk.simple.BlipModifierRobot;
/**
* Example robot that adds RTFM!! after each question mark.
* It assumes there is a manual for the conversation's themes.
*
*
@author
jerome baton : Wadael, http://blog.wadael.org
*/
@SuppressWarnings
(
"serial"
)
public
class
RTFMRobotServlet extends
BlipModifierRobot {
@Override
protected
String modifyBlipText
(
String actualText) {
if
(
actualText.indexOf
(
"?"
) ==
-
1
) return
null
;
else
{
return
actualText.replaceAll
(
"?"
, "? (RTFM!!"
) ;
}
}
}
VI. WadRobotFramework▲
VI-A. Principe▲
Le WRF est destiné à des programmeurs, il se présente sous la forme d'un projet pour Eclipse.
Ce projet contient les deux composantes du WRF :
- le générateur
- l'API
Chaque composant est lié à une étape du projet et rend plus rapide son déroulement.
Le générateur rend plus rapide la création du robot et l'API rend plus rapide l'écriture.
VI-B. Historique▲
Ce projet a suivi un développement incrémental depuis décembre 2009
Au début, fût l'API, elle permit de moins coder, puis vint le projet exemple qui permit de ne plus avoir à recréer tous les fichiers de configuration, puis l'API fût complétée par les robots avancés et enfin, arriva le générateur.
VI-C. API spécifique▲
L'API du WRF est une surcouche de l'API fournie par Google, elle définit un ensemble de classes notamment celles correspondant aux différents types de robots proposés par le WRF.
Elle s'utilise par simple héritage comme nous le verrons ultérieurement.
VI-D. Générateur▲
Le générateur est constitué d'un script Ant secondaire et de son fichier de configuration.
Il s'utilise à partir du script Ant principal (build.xml), où l'on choisit la cible (target) Ant à exécuter, correspondante au type de robot voulu.
Quelques secondes plus tard, vous disposerez d'un squelette de robot où seule la logique métier restera à implémenter.
VII. Utilisation du générateur▲
Pour utiliser le générateur, il est préférable de d'abord le configurer.
VII-A. Configuration du générateur▲
La configuration du générateur se fait en deux étapes. La première, que j'appelle "configuration générale" doit être réalisée une seule fois par station.
Quant à la "configuration pour un robot", elle est à faire pour chaque nouveau robot.
La durée cumulée de ces deux étapes est inférieure à deux minutes.
VII-A-1. Configuration générale▲
J'ai fait le choix qu'à chaque génération de robot, la librairie est compilée et son archive recréée. Cela m'a permis d'être certain que les robots successivement créés dans le cadre du développement de WRF l'étaient bien avec la dernière version.
La dépendance vers l'API de Google implique que cette dernière doit être dans le CLASSPATH utilisé par Ant lors de la compilation.
Il vous faut donc renseigner le fichier build.properties situé à la racine du projet pour que la clef plugin.lib.dir ait pour valeur le chemin du répertoire du plugin Eclipse où se trouvent les JAR de Google App Engine (exemple de JAR: appengine-local-runtime-shared.jar).
Exemple de chemin : c://tools//IDEs//eclipse35//plugins//com.google.appengine.eclipse.sdkbundle_1.2.6.v200910131704//appengine-java-sdk-1.2.6//lib//shared
Vient ensuite une configuration pour chaque robot que vous souhaitez créer.
VII-A-2. Configuration pour un robot▲
La personnalisation de la création d'un robot se fait également par l'utilisation d'un fichier de propriétés Java standard. Celui-ci a pour chemin generator/generator.properties, à partir de la racine du projet.
La configuration indique :
- le package à utiliser
- le nom du robot
- son numéro de version
- le nom de l'application de déploiement
- le domaine de l'application de déploiement
Des explications (en anglais) sont intégrées dans le fichier lui-même, mais comme le fichier proposé est déjà valorisé, il vous suffit de modifier les valeurs existantes par des valeurs 'correctes' correspondant à ce que vous souhaitez.
Après l'exécution, la configuration pour un robot est ensuite sauvegardée à la racine du répertoire dédié au robot généré.
VII-B. Exécuter le générateur▲
Dans le fichier build.xml à la racine du projet WRF, vous trouverez trois " target " Ant qui sont :
- generate_SimpleAppenderRobot
- generate_SimpleModifierRobot
- generate_AdvancedRobot
Exécutez celle qui correspond le mieux au robot que vous souhaitez créer.
Les différents types de robots sont expliqués ci-après.
VIII. Les types de robots▲
WRF définit plusieurs types de robots. A ce jour, il existe trois types de robots dont deux types simples et un type avancé.
VIII-A. Robots simples (RS)▲
Les robots simples réagissent à chaque blip ajouté à une conversation. Ils sont limités à du texte simple, sans mise en style.
VIII-A-1. Modifieurs-BlipModifierRobot▲
Un robot "modifieur" n'aura comme possibilités que
- modifier le blip
- ne pas modifier le blip
Dans le code source de votre robot, héritant de BlipModifierRobot, il vous faudra implémenter la méthode abstraite :
protected
abstract
String modifyBlipText
(
String actualText) ;
Si votre implémentation renvoie une chaîne non nulle, alors le blip sera modifié, avec pour contenu la chaine renvoyée par votre implémentation et votre robot sera ajouté comme auteur supplémentaire du blip.
Si votre robot renvoie null alors le blip restera inchangé sur les deux points.
VIII-A-2. Ajouteur-BlipAppenderRobot▲
Un robot "ajouteur" n'aura comme possibilités que
- ajouter un blip après le blip reçu
- ne pas ajouter de nouveau blip à la conversation
Dans le code source de votre robot, héritant de BlipAppenderRobot, il vous faudra implémenter la méthode abstraite :
protected
abstract
String getTextToAppend
(
String textOfTheBlipToReactFrom);
Si votre implémentation renvoie une chaîne non nulle, alors un nouveau blip sera créé, avec votre robot pour auteur.
Si votre robot renvoie null, alors la conversation restera inchangée (ni nouveau blip, ni le robot en tant que participant à la conversation).
VIII-B. Robots avancés (RA)▲
VIII-B-1. Définition d'un RA▲
Un RA est à voir comme une chaîne de production tayloriste basée sur la division du travail, car sa nature est d'être composé de plusieurs Workers chainés, qui réagissent chacun à une commande (ou non) mais peuvent aussi interrompre la chaine du traitement.
Un RA possède un identifiant (méthode getRobotIdentifier à surcharger) dont l'utilité est de permettre l'utilisation de plusieurs RA au sein d'une même conversation.
VIII-B-2. Définition d'un Worker▲
Un worker correspond à une tâche, une unité de travail. On les programmera à priori, de façon à ce qu'ils soient sans état. Dans l'implémentation, cela correspond à l'interface RobotWorker
Voici le code source de cette interface
public
interface
RobotWorker {
/**
* Returns a string identifying an instruction delimiting the scope of this robot.
* Can be null, so that the worker is executed whatever the instruction.
*/
public
String getInstruction
(
);
/**
* Returns a description of the instruction's behaviour.
* This description is used when the robot's usage is displayed.
*
@return
*/
public
String getDescription
(
);
/**
* Entry-point for a worker.
* You get all the objects you can use.
*
*
@param
bundle
*
@param
blip
*
@param
event
*
@param
parameters
may be null
*
@return
*
*/
public
boolean
doWork
(
RobotMessageBundle bundle, Blip blip, Event event, String parameters);
}
....
On y lit qu'une implémentation de worker doit définir les méthodes
- getInstruction
- getDescription et,
- doWork
Les noms sont assez explicites.
Il faut savoir que getInstruction et getDescription sont utilisées dans le cas où l'utilisateur demande de l'aide en créant un blip débutant par /help.
Quant à doWork, c'est dans cette méthode que vous définirez la logique du worker. En paramètres, vous disposez de tous les objets mis à disposition par l'API Google.
VIII-B-2-a. Worker sans papier (WSP)▲
Un WSP est un worker dont l'instruction est délibérément null c'est à dire que getInstruction() renvoie null.
Dans ce cas, le WSP sera exécuté pour chaque blip de la conversation à laquelle participe le RA et le WSP n'apparaitra pas dans les instructions déclarées par le RA en réaction à la demande d'aide de l'utilisateur.
VIII-B-3. Relation RA-Worker▲
Un RA peut posséder plusieurs workers, chacun pouvant être utilisé au sein de plusieurs RA. D'où l'attention à porter à ce qu'il soit sans état par défaut.
Les RA montrent leurs RobotWorkerlorsqu'un blip commence par /help
VIII-B-4. Différence avec les robots simples▲
Les RA diffèrent des RS sur deux points essentiels.
Le premier point est l'accès aux mêmes objets que l'API proposée par Google. Les RS les masquent pour une raison de simplicité
Le deuxième est la différence d'utilisation. Les RS ont des possibilités bien plus réduites que les RA.
VIII-B-5. Exemple de RA▲
Je vais reprendre ici une francisation de l'exemple que j'ai mis sur le wiki du projet. Sa valeur est uniquement pédagogique.
package
org.wadael.generated.advRobot.advAppender;
import
org.wadael.waverobotfrmwrk.advanced.RobotWorker;
import
org.wadael.waverobotfrmwrk.advanced.WithWorkersRobot;
import
com.google.wave.api.Blip;
import
com.google.wave.api.Event;
import
com.google.wave.api.RobotMessageBundle;
/**
* AdvAppenderExample
*
*
@author
generated by the WadRobotFramework
*
*/
@SuppressWarnings
(
"serial"
)
public
class
ExampleAjouteurAvanceServlet extends
WithWorkersRobot {
public
ExampleAjouteurAvanceServlet
(
){
super
(
);
/* On ajoute ici le ou les workers */
addRobotWorker
(
new
LengthWorker
(
) );
addRobotWorker
(
new
CapitalWorker
(
) );
}
@Override
public
String getRobotIdentifier
(
) {
return
"RA"
;
/* un identifiant identifie un RA dans une conversation, car il peut y en avoir plusieurs.
ASTUCE : FAIRE COURT !
*/
}
@Override
protected
String getRobotSelfIntroduction
(
) {
/* TODO Renvoyer le texte retourné par le robot quand il est ajouté à une conversation */
return
"Salutations."
;
}
@Override
protected
String getDisplayName
(
) {
return
"Robot avancé d'exemple pour Developpez.com"
;
}
}
/*
Premier worker
*/
public
class
LengthWorker implements
RobotWorker {
@Override
public
String getInstruction
(
) {
return
"taille"
;
}
@Override
public
String getDescription
(
) {
return
"Affiche la taille du blip."
;
}
@Override
public
boolean
doWork
(
RobotMessageBundle bun, Blip bli, Event eve,String params)
{
Blip lengthChild =
bli.createChild
(
);
lengthChild.getDocument
(
).append
(
"taille : "
+
bli.getDocument
(
).getText
(
).length
(
) +
" caractères"
);
return
true
;
}
}
/*
Deuxieme worker
*/
public
class
CapitalWorker implements
RobotWorker {
@Override
public
String getInstruction
(
) {
return
"capi"
;
}
@Override
public
String getDescription
(
) {
return
"Capitalise le texte du blip"
;
}
@Override
public
boolean
doWork
(
RobotMessageBundle bun, Blip bli, Event eve,String params)
{
Blip lengthChild =
bli.createChild
(
);
String capiTexte =
bli.getDocument
(
).getText
(
).toUpperCase
(
);
lengthChild.getDocument
(
).replace
(
capiTexte);
return
true
;
}
}
Les Worker doivent être définis dans leur propre fichier
VIII-B-6. Utilisation des RA▲
Là où les RS ont un comportement automatisé, les RA réagissent surtout à des commandes insérées par l'utilisateur au sein d'un blip. L'objectif principal de ce type de robot est qu'un même RA puisse réagir à plusieurs commandes différentes.
Les RA seront codés de telle manière que leur utilisation soit expliquée lorsqu'ils se présentent, en pointant vers un site web par exemple.
Les RA sont riches, riches de commandes.
Ils ont leurs commandes officielles (1 commande utilisateur = 1 worker implémenté). Ce sont celles qui sont listées lorsqu'un utilisateur valide un blip commençant par /help (valeur par défaut, reconfigurable).
Ils peuvent aussi avoir des commandes officieuses, de l'ombre. Elles correspondent aux workers faisant partie d'un RA mais retournant null comme instruction (méthode getInstruction() ).
Ils ont aussi des commandes standard, avec "/help" actuellement seule de cette catégorie mais qui sait ...
VIII-B-7. Les différents types de RA▲
Une sous-classe de RA a été créée afin d'obéir à la wavetiquette.
A savoir que l'usage est de ne se permettre d'ajouter un robot à une conversation uniquement si l'on est le créateur de la conversation.
Pour appliquer cela, il y a la classe CreatorObedientWithWorkersRobot.
Un autre type de RA est en préparation.
IX. Utilisation : pas à pas▲
Pour continuer ce tutoriel, il est temps d'abandonner la théorie pour passer à la pratique et créer un robot via le générateur.
Le point de départ est que tous les pré-requis sont satisfaits. Sous Eclipse, vous avez donc un project WadRobotFramework ouvert, créé à partir d'une archive ZIP récupérée sur le site.
1/ Adapter le fichier build.properties
2/ Configurer le générateur pour un résultat personnalisé, en adaptant le fichier generator/generator.properties
3/ Choisir un type de robot
4/ Lancer la tache Ant voulue (revoir le paragraphe 7)
Après ces quatre premières étapes, vous verrez dans la console d'Eclipse un message vous indiquant où trouver le squelette de robot généré.
Votre écran ressemble à la capture ci-dessous.
Le projet du robot que vous venez de créer se trouve dans generated_Robots. Il faut maintenant créer un nouveau projet pour votre robot afin qu'il soit pris en compte dans votre workspace.
Si votre Eclipse est en anglais, faites un clic droit dans la partie " Package Explorer " (à gauche) et choisissez " Import ". Puis " Existing project into workspace ", comme sur la capture ci-dessous.
Choisissez en " root directory " la racine du répertoire de votre robot fraichement généré.
L'astuce est de cocher la case "Copy projects into workspace". Cela permet de dupliquer l'arborescence (qui est générée dans $WRF_HOME$/generated_robots) à l'endroit voulu du workspace.
Ci-dessus, choix du répertoire "racine" du robot généré.
Dans cet exemple, mon robot était nommé "dev" comme on peut le voir dans la zone "Projects".
En cliquant sur "Finish", vous avez désormais votre projet de robot prêt à être terminé puis déployé. Le déployement se fait comme pour les autres applications web à la Google, à savoir qu'il est initié par le bouton à l'icone d'avion.
J'ai réalisé une vidéo de l'utilisation du générateur, vous la trouverez à l'adresse suivante :
https://www.youtube.com/watch?v=sdcPWz5ILEY
X. La suite▲
Que va-t'il se passer pour le WRF dans l'avenir ?
Pour répondre à cette question, le wiki possede une page WhatsNext sur laquelle j'essaie de centraliser les différents points qui seront traités ultérieurement, qu'ils soient des ajouts ou des modifications.
De nouvelles fonctionnalités seront ajoutées, parmi lesquelles :
- ne répondre qu'à une liste limitée d'utilisateurs (mise en place souscription)
- les commandes d'administration correspondantes
- générer des bots XMPP (utilisables dans Google Chat) et des robots ajouteurs en même temps (avec le même code métier) via un nouveau type de robot.
- Effacer les commandes (ou non) des blips
- Éventuellement, intégrer de nouveaux développeurs sur le projet.
- la création d'un nouveau type de robot (schizophrène)
XI. Conseils▲
Inscrivez-vous au groupe pour avoir des informations fraîches et/ou poser des questions.
Utilisez SVN plutôt que les distributions car une fois que vous aurez créé un projet WadRobotFramework dans votre workspace, il sera si simple de mettre WRF à jour.
XII. Liens▲
Le framework : http://code.google.com/p/wadrobotframework
Tutoriels en anglais, par Romin Irani :
- http://googlewaveexperiments.wordpress.com/2010/05/15/episode-2-writing-a-wave-robot-using-wadrobotframework/ (sans utiliser le générateur)
- http://gaejexperiments.wordpress.com/2009/12/03/episode-12-writing-an-advanced-google-wave-robot-using-wadrobotframework/
Je pense devoir préciser que Romin est un ami, mais cela ne change en rien la qualité de ses tutoriaux.
Il a publié un PDF regroupant l'ensemble des tutoriels (en anglais) qu'il a écrit sur Google App Engine et ses APIs.
Ce PDF est disponible à l'adresse suivante :
http://gaejexperiments.wordpress.com/gaej-experiments-ebook/
Liste des articles sur la programmation Wave :
http://code.google.com/intl/fr/apis/wave/articles.html
Ma présentation sur la v1 de WRF (partiellement périmée):
https://www.slideshare.net/wadael/wad-robot-framework-pour-jump-camp4-it
Mon site : http://www.wadael.org
Mon Twitter : http://twitter.com/wadael
A vos commentaires sur le forum 3 commentaires
XIII. Remerciements▲
Je remercie chaleureusement Wachter d'avoir effectué la relecture de cet article, ainsi que l'équipe de la rédaction de Developpez.com, Eric Siber, Caro-Line, Ricky81 et Hornetbzz pour leur accueil et leur aide.