Un court métrage d’animation à voir absolument !!
Quelques liens histoire de vous mettre l’eau à la bouche :
Une interview de l’équipe du film sur vimeo :
H5 Logorama from Etapes on Vimeo.
Un court métrage d’animation à voir absolument !!
Quelques liens histoire de vous mettre l’eau à la bouche :
Une interview de l’équipe du film sur vimeo :
H5 Logorama from Etapes on Vimeo.
Un autre film produit pendant le kino kabaret de Montpellier sur la méditerranée.
Je joue un des deux rôles du film alors je ne peux pas ne pas mettre la vidéo sur mon blog
Un film de PO : Il était un feu dans l’ouest.
De passage à Taratata.
Accessoirement, JIL a fait la musique de la pub Kenzo Flowers
Pranav Mistry pour TED india en dit un peu plus sur ses travaux de recherche et sur 6ème sens.
Enfin nous allons faire ce point tant attendu sur les niveaux d’accès en Java. Youpi !!!
Nous en profitons aussi pour faire un point syntaxe java.
La première partie de ce tutoriel vient en complément du tutoriel précédent sur la POO java. Dans le tutoriel précédent,vous avez pu voir comment déclarer des classes. Dans ce tutoriel, vous allez voir comment déclarer des attributs et des méthodes dans une classe et comment définir leurs niveaux de droit d’accès. En gros, comment écrire le corps d’une classe. Nous serons obligés pour être complet de présenter les règles d’écriture des “identifiers”. Ces mots qui vont vous permettre de nommer vos classes et vos variables. Nous ferons un tour des types primitifs en java, ça peut toujours servir. Puis pour être complet sur la syntaxe java, nous ferons un point sur les conditionnelles (if, while, for, …).
Les attributs, ou variables de classes, définissent un ensemble d’indicateurs de l’état des objets.
La classe définit les attributs et leurs types.
Un objet (instance de classe) a effectivement une liste d’attributs associés, ce sont des instances des attributs déclarés dans la classe. L’ensemble de ces valeurs définit l’état de l’objet, on les appelle d’ailleurs aussi variables d’état.
Les attributs sont typés. Ils peuvent être de type primitif ou être des objets.
La syntaxe pour déclarer un attribut est : le modifier de droit d’accés, le type de l’attribut, le nom de l’attribut. [modifier] [type] [nom de l'attribut] ;
exemple :
Eventuellement, vous pouvez aussi associer une valeur à l’attribut. Ce sera la valeur de l’attribut lors de l’instanciation d’un objet de la classe (sauf si vous modifiez cette valeur dans le constructeur) :
exemple :
Les modifiers d’accés permettent d’associer un droit d’accés à un attribut. Nous détaillerons les différents modifiers et leurs effets un peu plus loin dans ce tutoriel.
Les méthodes sont déclarées dans les classes, elles définissent le comportement des objets.
Elles peuvent être appelées par un objet, la syntaxe d’appel étant : monObjet.maMethode(param1, param2, …);
Lors de l’appel d’une méthode, celle-ci renvoie “quelque chose”. Cette “chose” peut être un objet, une valeur ou rien. Il faut donc préciser le type de ce qui est renvoyé par une méthode. Si la méthode ne renvoie rien, on utilise le mot clef void.
La syntaxe de déclaration d’une méthode est : le modifier de droit d’accés, le type de retour de la méthode, le nom de la méthode, les paramètres entre parenthéses, le corps de la méthode entre accolades.
[modifier] [nom méthode] ( [type][param1] , [type][param2] , [type][param3], …, [type][param n]) { [corps de méthode] }
Pour dire dans le corps de la méthode de renvoyer quelque chose, on emploie le mot clef return.
exemple :
public void setId( int nouvel_id ) { id = nouvel_id ; }
Pour préciser que l’on fait référence à l’id de notre objet, j’aurai pu écrire this.id au lieu de id. Mais dans ce cas, il n’y a pas de confusion possible, donc this n’est pas nécessaire.
exemple :
public void setId( int nouvel_id ) { this.id = nouvel_id ; }
L’opération de surcharge consiste à définir plusieurs méthodes ayant le même nom dans une même classe. Ces méthodes peuvent avoir des types de retour identiques ou différents. Par contre, il est obligatoire que le nombre ou le type des paramètres change.
L’opération de re-définition de méthodes concerne l’héritage et consiste à redéfinir dans une classe fille une méthode déjà définie dans une classe mère.
Nous allons maintenant présenter les différents modifiers et les droits d’accés qu’ils permettent de définir. Nous ne traitons ici que des modifiers d’accés.
Les modifiers d’accés sont :
Nous avons déjà vu dans les tutoriels précédents l’utilisation de default et public dans le cas de déclaration de classes. Encore une fois, default et public sont les seuls modifiers d’accés possibles sur des classes.
Nous allons traiter ici de quelques autres modifiers bien utiles: final, abstract et static.
Il faut retenir qu’il est possible d’associer plusieurs modifiers à une déclaration (que ce soit une classe ou un membre). Bien sûr, on ne peut utiliser qu’un seul modifier d’accés. Mais on peut faire des combinaisons avec les autres modifiers.
On peut par exemple déclarer un membre static et final et public.
Nous allons ici présenter les éléments de syntaxe essentiels pour les identifiers. Les identifiers étant les noms de variables (variables de classe, paramétres, variables locales), les noms de méthodes, les noms de classe.
Nous nous en tenons ici à ce qu’il est possible ou impossible de faire. Mais il existe beaucoup de bonnes pratiques ou conventions de codage que nous vous invitons à connaître et adopter : les javabeans (nous leur consacrerons un tutoriel) et la convention de codage recommandée par sun.
Il existe un plugin eclipse, check style qui vous permet de définir une convention de codage et de faire contrôler par eclipse que vous la respectez bien.
Il existe un ensemble de règles de bases (dites légales) à connaître concernant le nommage de classes, variables et méthodes.
Règles générales sur les identifiers :
La règle suivante n’est qu’une convention. Mais même eclipse vous rappelera à l’ordre si vous ne la respectez pas.
Ce sont aussi des conventions.
C’est encore une convention.
Les types primitifs en java sont représentés par des mots-clefs commençant par une minuscule. Le type String par exemple n’est pas un type primitif, c’est une classe héritant de Object.
Certaint types primitifs ont des équivalents objets comme int et Integer par exemple. La conversion entre int et Integer étant aisée et permettant de traiter des variables de type primitif comme des objets et vice versa.
Vous retrouverez ces informations sur la page de sun sur les types primitifs.
La liste des types primitifs :
Nous présentons ici les syntaxes de la plupart des conditionnelles Java. Sun les appelle les “control flow statements”, et leur consacre une partie de son tutoriel.
Les conditionnelles sont des sentences qui permettent de ne pas faire uniquement des exécutions linéaires du code. En règle générale, une ligne de code correspond à une instruction. Les instructions s’exécutent donc dans leur ordre d’apparition dans le code.
Les conditionnelles peremettent de casser cette linéarité en mettant en place des tests conditionnels (if then else) ou des boucles (for, while).
Il n’y a que deux conditionnelles à connaître : if et for.
A partir de ces deux conditionnelles toutes les autres peuvent être définies.
Exemple de if then else :
{
System.out.print(”test vrai”);
}
else
{
System.out.print(”test faux”);
}
il est possible d’enchaîner les tests de if. Par exemple :
{
System.out.print(”id = 0″);
}
else if (id == 1)
{
System.out.print(”id=1″);
}
else …
Il est aussi possible de ne pas préciser de else si on a aucun code alternatif à faire exécuter.
Exemple de for :
{
System.out.print( ” tour n°” + i );
}
Cette boucle s’exécutera 5 fois et affichera : tour n°0 tour n°1 tour n°2 tour n°3 tour n°4
Exemple de switch :
soit un int month représentant un mois. Le code suivant permet de tester la valeur de month et d’afficher le mois en lettres en fonction de sa valeur numérique.
{
case 1: System.out.println("January"); break;
case 2: System.out.println("February"); break;
case 3: System.out.println("March"); break;
case 4: System.out.println("April"); break;
case 5: System.out.println("May"); break;
case 6: System.out.println("June"); break;
case 7: System.out.println("July"); break;
case 8: System.out.println("August"); break;
case 9: System.out.println("September"); break;
case 10: System.out.println("October"); break;
case 11: System.out.println("November"); break;
case 12: System.out.println("December"); break;
default: System.out.println("Invalid month.");break;
}
Le mot clef case permet de préciser “si month prend cette valeur alors faire tout ce qui suit”.
Le mot clef default revient à dire “si la valeur n’est pas prise en compte par un case alors faire …”.
Le mot clef break permet de dire qu’il faut s’arréter là ou break est rencontré. En réalité, case dit c’est à partir d’ici qu’il faut exécuter. Et s’il n’y a pas de break, le code des case suivant est aussi exécuté.
Par exemple dans notre cas précédent, s’il n’y avait pas de break et avec month = 10, il serait affiché : October November December Invalid month.
Nous revenons sur break dans les interrupteurs de boucles.
exemple de while :
{
System.out.println(”toto”);
}
C’est un exemple de boucle infinie. Le test de notre while est un booléen vrai. Donc le corps du while sera exécuté à l’infini. Ce genre de code peut-être dangereux et très pratique. Très dangereux parce que l’on peut facilement faire une boucle infinie sans le vouloir. Mais parfois on a besoin de boucles infinies. Quand on veut garder des processus atifs par exemple.
Un exemple de do while :
{
System.out.println(”toto”);
}
while(false)
C’est l’exemple inverse du cas précédent. Ici “toto” sera affiché une fois uniquement. Le test du while étant faux, la boucle ne sera pas exécutée.
La grande différence entre while et do-while est que dans le cas du do-while, le test est exécuté à chaque fin de tour et non au début. Du coup, le corps de do est exécuté au moins une fois.
Nous en avons fini avec ce tutoriel sur la syntaxe et les niveaux de droits d’accés. Il ne vous reste plus qu’à pratiquer.
Dans la suite des tutoriels, nous allons nous orienter vers des composants logiciels java orientés pour du web essentiellement.
Il nous reste un cours sur les javabeans pour présenter une convention de nommage incontournable dans le monde professionnel. Un cours sur les Enums, qui permettent de définir des structures très utiles principalement pour le traitement de String.
Puis nous définirons un environnement de production qui nous semble otpimal pour des développements web (un ensemble de plugins eclipse, l’utilisation de Maven, et le framework hibernate).
Enfin, nous détaillerons les composants qui nous intéressent le plus, à savoir les Servlet et les Portlet.
Dans cet article, second de la série de nos tutoriels sur java, nous vous proposons une petite introduction à la POO (Programmation Orientée Objet). Il existe de nombreux tutoriels sur ce sujet. Nous essayons ici de rester simple et concis. Nous présenterons un exemple complet après un rapide cadre théorique.
Nous recommandons les excellents tutoriaux de sun à ce sujet.
Sur Wikipedia, on trouve cette définition :
La programmation orientée objet (POO) ou programmation par objet, a été élaborée par Alan Kay dans les années 1970. C’est un paradigme de programmation informatique qui consiste en la définition et l’interaction de briques logicielles appelées objets.
Qu’est-ce qu’un objet ? C’est une représentation informatique d’une entité physique ou d’une idée. Un objet est caractérisé par des attributs et des méthodes. On parle aussi de variables d’état (permettant de caractériser l’état de l’objet) et de comportements. Un objet est aussi une instance d’un modèle. Le modèle, que l’on appelle une Classe, représente donc un concept. Une classe est un descripteur des objets, elle va préciser quels sont les attributs (et les valeurs que ces attributs peuvent prendre) et méthodes de l’objet.
L’une des motivations de la programmation Objet est la réutilisabilité. Le but est que des classes définies pour un projet puissent être réutilisées dans d’autres sans avoir pour autant à comprendre le mécanisme interne de ces classes. Pour cela, deux notions importantes : celle d’interface et celle d’héritage.
Dans cette optique de réutilisabilité, il est important de souligner la possibilité de communiquer la signature d’une Classe. La signature d’une classe est sa description, la liste de ses attributs, la liste de ses méthodes. Cette description permet à tout un chacun de savoir comment peut être utilisé un objet d’une classe, comment on peut interagir avec un objet (certains diront “comment on peut communiquer avec cet objet”, pour moi on leur donne des ordres tout au plus, ce n’est pas une véritable communication). La signature permet de voir une Classe et ses instances comme une sorte de boîte noire dont on ne connait que les points d’entrées et de sorties. Ces signatures peuvent être commentées et publiées, c’est le cas de l’api en ligne ou javadoc.
C’est dans cette optique de signature qu’ont été définies les interfaces. On dit d’une interface que c’est un contract entre la classe et le monde extérieur. Une interface décrit exactement une signature mais restreinte à un ensemble de méthodes. Et une interface ne définit en aucun cas le fonctionnement de ses méthodes. Une classe qui implémente une interface garantit donc que tous les objets instances de cette classe ont une méthode qui s’appelle de cette façon et qui renvoie ce type de résultat.
L’héritage est la possibilité de spécialiser ou généraliser les Classes. Prenez une classe A avec ses attributs et ses méthodes. Une classe B doit avoir les mêmes attributs et méthodes mais avec quelques éléments en plus. On dit que B spécialise A. On peut alors grâce à l’héritage dire explicitement B est identique à A avec ces éléments supplémentaires. L’héritage permet d’économiser du code. Il est aussi possible de redéfinir l’une des méthodes de A dans B. Ainsi, B a bien une méthode portant le même nom que celle de A mais elle ne fait pas le même traitement. En gros, une ferrari et une deux chevaux sont toutes les deux des voitures qui peuvent accélérer mais pas de la même façon. Il est important de retenir que tout objet instance de B est aussi instance de A. C’est ce que l’on appelle le polymorphisme.
Dernier point sur l’héritage : dans certains langages, il est possible de faire de l’héritage multiple. L’héritage multiple consiste à dire : soit deux classes distinctes (non liées par héritage) A et B, une troisième classe C peut hériter de A et de B. C’est à dire que C hérite toutes les méthodes et attributs de A et de B. Il n’est pas possible en Java de faire de l’héritage multiple. Cependant, il est possible d’implémenter plusieurs interfaces.
De nombreux tutoriaux existent ou on vous fera coder des voitures ou des distributeurs de billets. Vous en trouverez de très bons sur développez par exemple.
Ici, nous allons nous contenter de l’essentiel. Comment on écrit une classe, comment on hérite d’une classe, comment on déclare une interface, comment on implémente une interface, et enfin comment une interface hérite d’une autre.
Je vous recommande de lire notre premier tutoriel débuter java. Nous ne détaillons toujours pas dans ce tutoriel tous les usages de tous les mots clefs java liés aux niveaux de droits d’accés. Nous consacrerons un tutoriel à ce sujet.
Avant de commencer, je voudrais insister sur l’ambiguité du mot objet. On l’utilise souvent à tort et à travers. On ne sait plus vraiment si on désigne une classe ou une instance de classe avec le mot objet. L’existence d’une classe Object en java n’aide pas à lever cette ambiguité. Donc une bonne fois pour toute : un objet est une instance d’une classe.
Avant tout un petit rappel sur les classes en Java:
Il faut aussi noter qu’une classe en Java est censée faire partie d’un package. Ceci n’est pas obligatoire mais c’est une bonne pratique. Dans Eclipse par exemple, quand vous créez une classe sans la mettre dans un package, celle-ci est placée dans un package par défaut (default package).
Donc en règle générale, un fichier .java débute par une ligne de déclaration de package, par exemple pour signaler que les classes de ce fichier sont dans le package tutoriels lui même inclus dans le package natoine, on écrira :
Un point sur les différents niveaux de droits d’accés pour les classes. Celles-ci peuvent avoir comme droit d’accés : default ou public.
Pour indiquer qu’une classe est de niveau d’accés par défaut ou publique, on utilise des mots-clefs que l’on appelle des modifiers. Le mot-clef pour le niveau par défaut est default, celui pour publique est public. En ce qui concerne le niveau d’accés par défaut, le mot-clef n’est pas indispensable. Ne rien mettre ou mettre le modifier default revient au même.
Pour déclarer une classe, on utilise le mot-clef class. Par convention, le nom d’une classe commence par une majuscule.
Déclaration d’une classe d’accés par défaut DefaultClass :
ou bien :
Déclaration d’une classe d’accés publique PublicClass :
Ensuite il faut ouvrir le corps de la définition de la classe par une acolade puis refermer cette acolade une fois la définition finie.
Pour hériter d’une classe, il faut utiliser le mot-clef extends. Par exemple nous allons faire un classe ExtendDefaultClass :
Vous remarquerez que vous êtes obligés de mettre cette nouvelle classe dans le même package que DefaultClass. Sinon, la classe DefaultClass ne sera pas visible.
A l’opposé si nous faisons unc classe ExtendPublicClass qui hérite de la classe PublicClass, nous pouvons la mettre dans un autre package que celui contenant la classe PublicClass.
Il reste deux modifiers important à aborder concernant la définition de classes. Ces mots-clefs sont final et abstract :
Déclarons une classe final FinalExtendDefaultClass qui hérité de DefaultClass :
Déclarons une classe abstraite AbstractPublicClass qui hérite de la classe PublicClass :
Pour déclarer une interface, il faut utiliser le mot-clef interface. Les interfaces comme les classes peuvent être accessible par défaut ou publique. Elles suivent les mêmes règles de droit d’accés et les modifiers d’accés sont les mêmes (default, public).
L’intérêt d’une interface est de préciser des méthodes à obligatoirement implémenter. Une classe implémentant une interface doit nécessairement implémenter les méthodes de cette interface.
Pour l’exemple, nous allons déclarer une interface publique PublicInterface avec une méthode printName().
Petite remarque au sujet des méthodes d’une interface (pour ceux qui ont pris de l’avance concernant les droits d’accés des méthodes) : elles sont abstraites et publiques obligatoirement. Elles sont nécessairement publiques parce que sinon, elles ne seraient pas visibles par les classes qui doivent les implémenter. Et elles sont abstraites parce que chaque classe doit définir leur implémentation et l’interface ne suppose rien d’autre au sujet des classes (l’interface ne sait pas quels sont les attributs des classes l’implémentant ni les autres méthodes).
La méthode printName aurait pu être écrite de la façon suivante, cela revient au même :
Pour qu’une classe implémente une interface, il faut utiliser le mot-clef implements et bien sur, déclarer et implémenter les méthodes de l’interface en question. Par exemple, nous allons déclarer une classe publique PublicClassImplementPublicInterface.
Si une classe doit implémenter plusieurs interfaces, il suffit de séparer chaque nom d’interface par une virgule.
Une classe peut hériter d’une autre classe et implémenter une ou plusieurs interfaces. Dans ce cas, le mot clef extends et la déclaration de la classe mère précéde le mot-clef implements et la liste des interfaces. Par exemple :
Il est possible pour une interface d’hériter d’une autre interface. Il suffit de préciser l’interface héritée par le mot-clef extends.
Déclarons une interface InterfaceExtendsPublicInterface qui hérite de notre interface précédente PublicInterface :
Cette interface n’a pas à redéclarer les méthodes héritées par ses interfaces mères mais les classes implémentant cette interface devront les implémenter.
Instancier un objet se fait simplement par l’utilisation du mot clef new. Par exemple, instancions un objet de la classe PublicClassImplementInterface:
Lors de l’appel à new PublicClassImplementPublicInterface(), un nouvel objet de la classe PublicClassImplementPublicInterface est construit. Cette construction fait appel au constructeur de la classe PublicClassImplementPublicInterface.
Dans notre exemple, nous n’avons pas défini de constructeur dans la classe PublicClassImplementPublicInterface. Du coup, le constructeur appelé est celui de la classe dont hérite PublicClassImplementPublicInterface. Si celle-ci ne définit pas de constructeur non plus, le constructeur appelé est celui de la classe mère de la classe dont hérite PublicClassImplementPublicInterface. Etc jusqu’à la classe Object qui elle déclare bien un constructeur.
En java, il existe une super classe, la classe Object. Toutes les classes que vous définirez héritent donc de cette classe Object et ce sans avoir à utiliser le mot-clef extends.
Nous allons maintenant déclarer une classe FinTutoClass qui elle déclare un constructeur. Un constructeur de classe doit porter le même nom que la classe et se déclare de la même façon qu’une méthode à part qu’il n’a pas de type de retour. Afin de bien finir ce tutoriel, cette classe FinTutoClass hérite de la classe PublicClassExtendsImplements et implémente l’interface InterfaceExtendsPublicInterface.
Encore une fois, le constructeur peut avoir le même niveau de droits que toute méthode (donc default, public, private ou protected).
L’utilisation de super(); signifie que le constructeur a le même comportement que le constructeur de la classe mère. Ensuite il est toujours possible d’ajouter d’autres instructions. En réalité, super() est appelé dans tous les cas.
Maintenant nous allons consacrer la fin de ce tutoriel au polymorphisme. Nous allons écrire une classe MainClass avec une méthode main afin de pouvoir l’exécuter. Les questions auxquelles nous allons tenter de répondre sont : quelle est la nature (ou le type) de notre objet? Peut-il changer de nature?
Cette dernière partie va nous permettre d’introduire l’opération de casting d’une classe. Le casting d’une classe (on dit que l’on caste un objet d’une classe) consiste à demander à un objet d’agir en tant qu’objet d’un autre type que celui déclaré lors de sa construction. Il est possible de caster l’objet selon les classes dont il est instance (c’est à dire la classe déclarée lors de l’appel à new et toutes les classes méres) et selon les interfaces qu’il implémente.
Le contenu de la classe MainClass :
Que fait-on dans ce main?
Vous pouvez télécharger le contenu de mon projet eclipse pour ce tutoriel.
Bien entendu les noms de classe ont ici été choisis pour le tutoriel. Vous n’êtes pas obligé de mettre le mot Default dans le nom d’une classe d’accés pas défaut.
Un tutoriel sur la communication interportlet. Les ressources sur le sujet sont encore rares, il m’a semblé nécessaire de faire ce tutoriel assez rapidement du coup.
Si vous suivez les autres tutoriels de ce site sur la programmation JAVA, il arrive bien en avance de ce qui était prévu. Mais je le réintégrerai plus tard dans un tutoriel plus long consacré aux portlets.
Pour l’instant, ce tutoriel va traiter de la communication entre portlet conforme à la JSR286.
En particulier nous ne traiterons que de la communication par passage d’événement. Cette communication étant à nos yeux la plus compatible avec une vision composant. Pour ceux qui veulent en savoir plus, la ressource issue du blog xebia est la meilleure référence que j’ai trouvé. Dans cette ressource, vous retrouverez l’essentiel de ce qui est détaillé ici et une explication de l’autre solution de communication qu’est le partage d’état. Il y a aussi une discussion dans un des forums de JBoss.
Je précise que dans le cadre de ce tutoriel, les portlets ont été développés sous eclipse (mais ça n’a pas d’importance) et déployés sous JBoss Portal (version 2.7 + AS 4.2.3).
Cependant, le tutoriel s’adresse à tous développeurs de portlet 2.0, c’est à dire dans le cadre d’un développement de portlet pour un portail respectant la JSR286.
Il y a deux façons de communiquer avec la JSR 286. La première solution est le partage d’état. Nous ne détaillerons pas dans ce tutoriel cette solution mais allons en expliquer le principe. La deuxième solution, celle que nous détaillerons ici en pratique est le passage d’événement. Ce paragraphe va donc exposer les principes de ces deux solutions et va nous permettre de justifier pourqoi le passage d’événement nous semble plus proche d’une approche composant et donc d’un développement orienté vers l’intégration de composants.
Le partage d’état : dans cette solution, chaque portlet déclare les paramètre qu’il partage avec les autres portlets et chaque portlet déclare les paramètres des autres portlets qu’il veut pouvoir atteindre. Ainsi, au moment ou un portlet effectue son rendu (calcule sa vue), il rend ses paramètres visibles ou accéde à ceux des autres.
Le passage d’événement : dans cette solution, chaque portlet déclare les événements qu’il peut lever et les événements qu’il peut écouter. Un portlet léve ensuite un événement, et les portlets écouteurs sont automatiquement au courant.
Discussion : La première solution (celle du passage d’état) peut être recommandée quand les paramètres échangés ne sont utiles que pour l’affichage. La solution est facile à mettre en place, il suffit de déclarer dans le descripteur du portlet les paramétres partagés. Cependant, cette solution n’est pas recommandé quand les paramétres doivent être traités (c’est à dire quand ils risquent d’être modifiés par un calcul effectué par un autre portlet) car les paramètres ne sont échangés qu’au moment de l’appel à la méthode Render. Mais la principale critique est que cette solution rend les portlets fortement dépendants les uns des autres puisque ils supposent l’existence de ces paramètres afin de rendre leur affichage. La deuxième solution quand à elle permet d’effectuer des traitements sur les paramètres et reste très proche d’une vision composant. Le mécanisme d’événements garantit que si le paramètre existe il y aura traitement, et que si le paramètre n’existe pas, il y aura un fonctionnement par défaut.
Alors en pratique comment cela fonctionne? L’exemple que je vous propose est très simple: nous développons deux portlets, un PortletA et un PortletB. Chaque portlet a son propre projet dans Eclipse (bien que j’aurai pu faire un seul projet, mais pour l’exemple, je voulais détailler un cas ou les portlets auraient pu être développés sans connaissance l’un de l’autre). Le PortletA sera l’écouteur d’événement, le PortletB se chargera de l’envoi. L’événement levé permet d’échanger une donnée de type String.
Il est possible d’échanger autre chose que des String. Tout objet serializable peut être échangé par passage d’événement.
Les erreurs classiques à éviter (si je le dis c’est que je suis passé par là croyez-moi
) :
Il faut déclarer le type des paramétres échangés, ou des event levés si vous préférez. Pour cela, il faut modifier le descripteur de l’application portlet.
Il faut ajouter un noeud <event-definition> comme fils du noeud <portlet-app> dans votre fichier portlet.xml.
PortletB
Dans l’exemple, le descripteur portlet.xml associé au projet du portletB devient :
<?xml version=”1.0″ encoding=”UTF-8″?>
<portlet-app xmlns=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”
version=”2.0″
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”>
<portlet>
<portlet-name>PortletB</portlet-name>
<portlet-class>tuto.portlet.PortletB</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Enverra des infos à Portlet A</title>
</portlet-info>
<supported-publishing-event>
<qname>totoString</qname>
</supported-publishing-event>
</portlet>
<event-definition>
<qname>totoString</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</portlet-app>
J’ai décidé de passer des String uniquement comme paramétre et d’appeler cet événement “totoString”.
Au niveau du code, j’ai décidé de faire un simple portlet qui charge un jsp et qui léve l’événement totoString lors d’une action. L’action est réalisé lors d’un clic sur un lien dans le portlet (cf portletB.jsp).
Le code du PortletB :
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
public class PortletB extends GenericPortlet
{
protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws IOException, PortletException
{
rResponse.setContentType(”text/html”);
PortletRequestDispatcher prd;
prd = getPortletContext().getRequestDispatcher(rResponse.encodeURL(”/WEB-INF/jsp/portletB.jsp”));
prd.include(rRequest, rResponse);
}
public void processAction(ActionRequest request, ActionResponse response)
throws PortletException,IOException {
System.out.println(”processAction”);
this.sendEvent(response);
}
public void sendEvent(ActionResponse response)
{
String _toto = “passée en event”;
response.setEvent(”totoString”, _toto);
}
}
Le fichier portletB.jsp :
<%@ page language=”java” contentType=”text/html; charset=UTF-8″
pageEncoding=”UTF-8″%>
<%@ taglib uri=”http://java.sun.com/portlet_2_0″ prefix=”portlet” %>
<portlet:defineObjects/>
HelloWorld !!! Portlet B!
<a href=”<portlet:actionURL/>” >Envoi de l’event</a>
PortletA
Le PortletA est le portlet traitant un événement. Il doit donc implémenter l’interface EventPortlet et sa méthode processEvent(EventRequest request, EventResponse response). La méthode processEvent sera automatiquement appelé lorsque un événement du type de ceux déclaré dans le descripteur portlet.xml sera levé par un autre portlet.
Le descripteur portlet.xml de PortletA :
<?xml version=”1.0″ encoding=”UTF-8″?>
<portlet-app xmlns=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”
version=”2.0″
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”>
<portlet>
<portlet-name>PortletA</portlet-name>
<portlet-class>tuto.portlet.PortletA</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Recevra des infos de Portlet B</title>
</portlet-info>
<supported-processing-event>
<qname>totoString</qname>
</supported-processing-event>
</portlet>
<event-definition>
<qname>totoString</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</portlet-app>
Le code de PortletA :
import java.io.IOException;
import java.io.PrintWriter;
import javax.portlet.Event;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.EventPortlet;
public class PortletA extends GenericPortlet implements EventPortlet
{
protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws IOException, PortletException
{
if(rRequest.getParameter(”stringEvent”)!=null)//Action avec Event
{
rResponse.setContentType(”text/html”);
PrintWriter writer = rResponse.getWriter();
writer.write(”Event value of totoString : ” + rRequest.getParameter(”stringEvent”));
writer.close();
}
else //Action sans Event
{
rResponse.setContentType(”text/html”);
PortletRequestDispatcher prd;
prd = getPortletContext().getRequestDispatcher(rResponse.encodeURL(”/WEB-INF/jsp/portletA.jsp”));
prd.include(rRequest, rResponse);
}
}
public void processEvent(EventRequest request, EventResponse response)
{
Event event = request.getEvent();
String _toto = “vide”;
if(event.getName().equals(”totoString”))
{
_toto = (String)event.getValue();
response.setRenderParameter(”stringEvent”, _toto);
}
}
}
Le jsp de PortletA n’a aucune importance étant donné que c’est uniquement du HTML au final. Pour varier les plaisirs j’ai préféré utiliser un printWriter pour l’affichage après traitement de l’événement. Le but étant juste ici de constater visuellement que le PortletA a bien reçu l’événement. Dans un cas concret, il n’est pas forcément nécessaire de modifier le rendu du PortletA une fois l’événement traité.
Une fois déployés les deux portlets s’affichent ainsi :
Une fois cliqué sur le lien “Envoi de l’event” :
J’espére que ce tutoriel court et rapide vous aura suffisament éclairé et vous fera gagner du temps. Le plus difficile concernant l’IPC étant encore de trouver de la documentation.
Vous pouvez télécharger les sources de ce tutoriel.
C’est pas nouveau comme vidéo. Mais l’article de Vanksen sur les tendances du marketing 2010 fait référence à cet exposé de Pattie Maes à TED.
L’avenir de l’internet mobile…
Action discrète s’invite à un débat sur l’identité nationale.
Un bel exemple de ce que peut devenir un débat public…