Mise en œuvre de composants Web via le framework Ellipse

Alexia Ramaïoli & Dominique Liard

Ellipse Framework est une solution de développement d'applications Web à base de technologies Java et JavaScript. Le but de ce framework est de vous garantir une « haute productivité » lors de la mise en œuvre de vos applications Web. Pour ce faire, un grand nombre d'éléments logiciels vous sont directement proposés par le framework afin d'adresser les principales problématiques de la mise en œuvre d'une application Web. Si vous choisissez le framework Ellipse pour vos développements d'applications Web en Java, il ne vous sera plus nécessaire de chercher à intégrer un certain nombre de solutions distinctes (un framework de développement Web en Java, un moteur de services Web, une API JavaScript complémentaire…) étant donné que le framework Ellipse cherche à répondre à cette problématique.

Parmi les principaux aspects traités par le framework, nous pouvons citer : concept de pages Web, de composants Web réutilisables et de services Web, API côté serveur en Java, API côté client en JavaScript, documentations Java/JavaScript fusionnées, composants Web évolués (DataGrid, histogrammes graphiques à partir de modèle de données, camemberts…), outils d'aide au débogage (moteur de traces), moteur de recherche intégré, moteur de statistiques de navigation… Notez aussi qu'un plugin pour l'EDI Eclipse a été développé afin de faciliter l'utilisation du framework : le plugin Ellipse. Ellipse Framework, ainsi que son plugin sont développés par la société Infini Software.

L'objectif de ce tutoriel est de vous montrer comment créer des composants Web réutilisables via le framework Ellipse. Deux types de composants Web peuvent être envisagés : un composant Web définit dans une simple classe Java, ou bien un composant Web à base d'un modèle XML (TemplatedComponent) afin d'y stocker la mise en page pour le rendu HTML. Bien entendu, nous allons utiliser le plugin Ellipse afin de nous simplifier la construction de ces éléments.

Pour réagir à ce tutoriel, un espace de dialogue vous est proposé sur le forum Commentez

- Titre : Mise en œuvre de composants Web via le framework Ellipse

- Auteur : Alexia Ramaïoli & Dominique Liard

- Parution : 13 octobre 2011

- Mise à jour : 5 mars 2020

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2011 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Coder une classe de composant Ellipse sans rendu HTML

- II. Coder une classe de composant Ellipse avec rendu HTML

- III. Intégration d'un composant dans une page Ellipse

- IV. Ajout de propriété à notre composant Ellipse

- V. Utilisation d'un TemplatedComponent

- VI. Remerciements

I - Coder une classe de composant Ellipse sans rendu HTML

Un composant Ellipse doit, au minimum, dériver de la classe corelib.services.web.components.WebComponent. Attention : cette classe ne fournit pas de support en termes de rendu HTML. Néanmoins l'utilisation de ce type de base peut s'avérer utile dans certains cas particuliers : exécution d'un traitement particulier, initialisation d'un contexte…

Exemple de composant Web Ellipse sans rendu HTML

1. package corelib.services.web.samples.virtualcaddy.webcomponents;

3. import corelib.services.web.components.WebComponent;

5. public class MinimalComponent extends WebComponent {

7. public MinimalComponent() {

8. // CAUTION : print a message to the Web server logs

9. // Not in the HTML result !!!

10. System.out.println( "Hello" );

11. }

13. }

Notez bien que dans l'exemple ci-dessus, la ligne 10 n'affiche strictement rien sur la page Web qui utilisera ce composant. Généralement, le flux standard de sortie (System.out) d'un serveur Web est redirigé vers un fichier de log : c'est dans ce fichier que le message sera produit. Dans le cas d'un serveur Tomcat, vous devriez normalement retrouver ce fichier de log à l'emplacement suivant : $CATALINA_HOME/logs/catalina.out

II - Coder une classe de composant Ellipse avec rendu HTML

Si vous souhaitez que votre composant ait le support de rendu HTML, il vous faudra alors utiliser le type de base suivant : corelib.services.web.components.VisualComponent. Cette classe dérive bien entendu de la class corelib.services.web.components.WebComponent.

Tout comme une page Ellipse, un composant a un cycle de vie qui lui est propre. Ce cycle de vie sur vos composants se traduit par des invocations de méthodes sur vos composants à différents moments. Pour que vos composants se comportent correctement, il faut donc qu'ils redéfinissent certaines méthodes. Ces méthodes sont initialement définies sur les classes corelib.services.web.components.WebComponent et corelib.services.web.components.VisualComponent. Pour de plus amples informations sur ces classes, vous pouvez consulter la Javadoc du framework Ellipse.

Exemple de composant Web Ellipse avec rendu HTML

1. package corelib.services.web.samples.virtualcaddy.webcomponents;

3. import java.io.PrintWriter;

5. import corelib.services.web.components.VisualComponent;

6. import corelib.services.web.webapplications.events.WebPageEvent;

8. public class CaddyFooter extends VisualComponent {

10. @Override public void component_renderBegin( WebPageEvent webPageEvent ) {

11. PrintWriter out = this.webPage.getOut();

12. out.println( "\n<hr/>" );

13. out.println( "<div align='center'>" );

14. }

16. @Override public void component_renderChildren( WebPageEvent webPageEvent ) {

17. PrintWriter out = this.webPage.getOut();

18. out.println( "    <a href='http://www.infini-software.com'>Ellipse</a>" );

19. out.println( "    sample web application - " );

20. out.println( "    <a href='Trace.wp'>View web trace</a>" );

21. }

23. @Override public void component_renderEnd( WebPageEvent webPageEvent ) {

24. PrintWriter out = this.webPage.getOut();

25. out.println( "</div>" );

26. }

28. }

L'exemple ci-dessus vous propose donc une classe permettant de générer un composant de pied de page. Cette classe de composant dérive donc de la classe VisualComponent et en redéfinit trois méthodes :

- public void component_renderBegin( WebPageEvent webPageEvent ) : cette méthode produit le flux HTML résultant de l'utilisation du tag ouvrant pour le composant Ellipse considéré ;

- public void component_renderChildren( WebPageEvent webPageEvent ) : cette méthode est invoquée pour générer le HTML équivalent au contenu saisi entre le tag ouvrant et le tag fermant du composant Ellipse considéré ;

- public void component_renderEnd( WebPageEvent webPageEvent ) : permet de générer la partie finale du rendu HTML du composant Web.

Ces trois méthodes acceptent un paramètre de type WebPageEvent nous donnant accès à des informations complémentaires sur chaque événement. De plus, par le biais de la classe VisualComponent (que l'on hérite) vous avez accès à d'autres informations et notamment la page Web dans laquelle le composant sera utilisé.

III - Intégration d'un composant dans une page Ellipse

Une fois votre composant terminé, vous pouvez directement le tester dans une page Web Ellipse. La page ci-dessous vous montre comment tester, très simplement, votre composant : notez qu'on n'utilise pas de classe de page Ellipse. Effectivement, et dans ce cas très simpliste, nous souhaitons simplement tester le rendu HTML.

Intégration du composant dans une page Web

1. <?xml version="1.0" encoding="ISO-8859-1" ?>

2. <web:Html xmlns:web="corelib.services.web.components"

3. xmlns:demo="corelib.services.web.samples.virtualcaddy.webcomponents"

4. codeBehind="corelib.services.web.webapplications.WebPage">

5. <head>

6. <title>Web component Sample</title>

7. <link rel="stylesheet" type="text/css" href="CssStyles.css" />

8. </head>

9. <body>

10. <h1>Web component Sample</h1> <br />

12. <demo:CaddyFooter />

14. </body>

15. </web:Html>

L'injection du composant dans la page Ellipse se fait en deux étapes. Premièrement, en ligne 03, nous définissons un alias demo qui pointe vers le package dans lequel nous avons placé la classe Java de notre composant. Puis, en second lieu, nous avons placé un composant CaddyFooter dans la page, en ligne 12. Déployez sur Tomcat, puis testez : vous devriez obtenir l'affichage suivant.

Utilisation du composant Web

IV - Ajout de propriété à notre composant Ellipse

Si vous cherchez à faire des composants Ellipse plus sophistiqués, sachez que vous pouvez aussi leur associer des propriétés. Au niveau d'un composant, une propriété se définit de manière traditionnelle en respectant le standard JavaBeans (utilisation des conventions de codage pour les getters et les setters). Voici un exemple de composant supportant une propriété.

Définition d'une propriété sur une classe de composant Web

1. package corelib.services.web.samples.virtualcaddy.webcomponents;

3. import java.io.PrintWriter;

5. import corelib.services.web.components.VisualComponent;

6. import corelib.services.web.webapplications.events.WebPageEvent;

8. public class LanguageSelector extends VisualComponent {

10. private String currentLanguage = "fr";

13. public String getCurrentLanguage() {

14. return currentLanguage;

15. }

17. public void setCurrentLanguage( String currentLanguage ) {

18. this.currentLanguage = currentLanguage;

19. }

22. @Override public void component_renderBegin( WebPageEvent webPageEvent ) {

23. PrintWriter out = this.webPage.getOut();

24. String imageStyle = "style='border: 0px; cursor: pointer;'";

26. out.println( "<div>" );

27. out.println( "    <script language='javascript'>" );

28. out.println( "        function changeLanguage( language ) { " );

29. out.println( "            var inputNode = document.getElementById('"+this.getId()+"');");

30. out.println( "            inputNode.value = language;" );

31. out.println( "            inputNode.form.submit();" );

32. out.println( "        }" );

33. out.println( "    </script>" );

34. out.println( "    <img src='Images/LocaleFR.png' onclick='changeLanguage(\"fr\");'" );

35. out.println( "         title='Changer le language en fran&ccedil;ais' " + imageStyle + "/>");

36. out.println( "    <img src='Images/LocaleEN.png' onclick='changeLanguage(\"en\");'" );

37. out.println( "         title='Change language to english' " + imageStyle + "/>" );

38. out.println( "    <input type='hidden' id='" + this.getId() + "'" );

39. out.println( "           name='" + this.getId() + ":currentLanguage'" );

40. out.println( "           value='" + this.currentLanguage + "' />" );

41. out.println( "</div>" );

42. }

44. }

Comme vous pouvez le voir en ligne 10, l'exemple ci-dessus, définit un attribut privé currentLanguage. Il définit aussi les deux méthodes d'accès (getCurrentLanguage et setCurrentLanguage). C'est par l'intermédiaire de ces deux méthodes que la page Web va configurer l'état de votre composant. Ensuite la méthode component_renderBegin de rendu HTML (ici, nous avons décidé de placer tout le code dans cette méthode - pas de component_renderChildren et de component_renderEnd) utilise, bien entendu, l'état courant en utilisant la valeur stockée pour le langage. Il nous faut maintenant définir la page Web Ellipse qui va contenir une instance du composant.

Affectation de la propriété via un attribut XML

1. <?xml version="1.0" encoding="ISO-8859-1" ?>

2. <web:Html xmlns:web="corelib.services.web.components"

3. xmlns:demo="corelib.services.web.samples.virtualcaddy.webcomponents"

4. codeBehind="corelib.services.web.webapplications.WebPage">

5. <head>

6. <title>User component Sample</title>

7. <link rel="stylesheet" type="text/css" href="CssStyles.css" />

8. </head>

9. <body>

10. <h1>User component Sample</h1> <br />

12. <demo:CaddyFooter />

13. <demo:LanguageSelector currentLanguage="fr" />

14. </body>

15. </web:Html>

La ligne 13 injecte donc un composant Web de sélection de langue dans la page Web considérée. Notez bien que l'attribut XML currentLanguage est bien associé à une propriété : il impose donc la présence de la méthode setCurrentLanguage dans la classe de composant : il vous suffit de réaliser des traces dans cette méthode pour valider les appels.

V - Utilisation d'un TemplatedComponent

Une des parties les plus délicates, lors de la mise en œuvre d'un composant Web réutilisable, est la génération du flux HTML correspondant au composant Web. Dans le but de vous simplifier cette étape, il est possible de définir un composant basé sur le template (un modèle) XML/HTML. Ainsi, plutôt que de produire les tags correspondants par code Java, vous pouvez simplement les définir dans le fichier définissant le template du composant.

Pour créer un nouveau « TemplatedComponent », le mieux est d'utiliser l'assistant correspondant dans le plugin Ellipse. Pour ce faire, cliquez avec le bouton droit de la souris et sélectionnez le menu New, puis Web Component, comme le montre la capture d'écran ci-dessous.

Lancement de l'assistant de création d'un nouveau composant Web.

La boîte de dialogue ci-dessous devrait à son tour apparaître : elle permet de spécifier certaines caractéristiques du composant à développer. Notez que cet assistant aurait pu nous servir à produire le fichier pour le composant précédemment développé : dans ce cas-là, il aurait fallu laisser décochée la case « Is a templated component? ». Par contre, pour produire un TemplatedComponent, prenez soin de cocher cette case. Ensuite, renseignez les autres champs de la boîte de dialogue comme proposé dans cette capture d'écran, puis cliquez sur le bouton Finish.

L'assistant de création d'un nouveau composant Web.

Une fois la boîte de dialogue fermée, l'assistant doit avoir produit deux fichiers. Ces deux fichiers doivent être localisés dans le même dossier. Le fichier MyTemplatedComponent.java définit la structure de tags HTML/XML à injecter en lieu et place de votre tag <MyWebComponent />. Voici, à titre d'exemple, le code produit par l'assistant.

La structure HTML/XML de votre composant Web

1. <?xml version="1.0" encoding="ISO-8859-1" ?>

2. <div xmlns:web="corelib.services.web.components" style="background: lightGray; border: 1px solid black;">

3. <web:Label id="lblMessage" for="txtMessage" text="Message" />

4. <web:TextBox id="txtMessage" />

5. <web:Button id="btnMessage" />

6. <br/>

7. </div>

Comme vous pouvez le constater, un TemplatedComponent peut utiliser d'autres composants serveur Ellipse (via les tags préfixés par web: dans l'exemple considéré). Ils seront eux aussi transformés par le moteur Ellipse.

Si vous avez ouvert le fichier précédent avec le plugin Ellipse, notez qu'un second onglet est disponible en bas de la fenêtre d'édition du document. Cet onglet permettra de consulter l'autre fichier, bien qu'il soit possible de l'ouvrir directement via un éditeur Java. Voici, toujours à titre d'exemple, le contenu de ce second fichier, MyTemplatedComponent.java.

Le code Java de votre composant Web

1. package com.is.demo;

3. import corelib.services.web.components.Button;

4. import corelib.services.web.components.Label;

5. import corelib.services.web.components.TextBox;

6. import corelib.services.web.components.TemplatedComponent;

7. import corelib.services.web.webapplications.events.WebPageEvent;

9. public class MyTemplatedComponent extends TemplatedComponent {

11. private Label    lblMessage;

12. private TextBox    txtMessage;

13. private Button    btnMessage;

15. public void component_load( WebPageEvent event ) {

16. if ( this.getWebPage().getRequest().getParameter( btnMessage.getId() ) != null ) {

17. System.out.println( txtMessage.getValue() + " entered" );

18. }

19. }

21. }

Remarquez qu'il sera alors possible d'accéder aux différents éléments du composant principal. De même, un composant à base de template sera assujetti au même cycle de vie qu'un composant Ellipse n'utilisant pas de template. Il ne vous reste plus maintenant qu'à injecter votre nouveau composant dans une page Web de test, comme le montre l'exemple suivant. Veuillez, ensuite, afficher votre page dans un navigateur Web.

Intégration du composant templaté dans une page Web

1. <?xml version="1.0" encoding="ISO-8859-1" ?>

2. <web:Html xmlns:web="corelib.services.web.components"

3. xmlns:demo="com.is.demo"

4. codeBehind="corelib.services.web.webapplications.WebPage">

5. <head>

6. <title>Web component Sample</title>

7. <link rel="stylesheet" type="text/css" href="CssStyles.css" />

8. </head>

9. <body>

10. <h1>Web component Sample</h1> <br />

12. <web:Form>

13. <demo:MyTemplatedComponent />

14. </web:Form>

16. </body>

17. </web:Html>

Il est aussi possible d'ajouter une (ou plusieurs) propriété à votre composant Web. À titre d'exemple, ajoutons une propriété permettant de rendre read-only ou non le champ de saisie du composant.

Le code Java de votre composant Web

1. package com.is.demo;

3. import corelib.services.web.components.Button;

4. import corelib.services.web.components.Label;

5. import corelib.services.web.components.TextBox;

6. import corelib.services.web.components.TemplatedComponent;

7. import corelib.services.web.webapplications.events.WebPageEvent;

9. public class MyTemplatedComponent extends TemplatedComponent {

11. private Label    lblMessage;

12. private TextBox    txtMessage;

13. private Button    btnMessage;

15. private boolean  readOnly;

17. public boolean isReadOnly() {

18. return this.readOnly;

19. }

21. public void setReadOnly( boolean state ) {

22. this.readOnly = state;

23. }

25. public void component_load( WebPageEvent event ) {

26. this.txtMessage.setReadOnly( this.readOnly );

28. if ( this.getWebPage().getRequest().getParameter( btnMessage.getId() ) != null ) {

29. System.out.println( txtMessage.getValue() + " entered" );

30. }

31. }

33. }

Pour utiliser ce composant et sa propriété, procédez comme ci-dessous.

Composant templaté avec une propriété

1. <?xml version="1.0" encoding="ISO-8859-1" ?>

2. <web:Html xmlns:web="corelib.services.web.components"

3. xmlns:demo="com.is.demo"

4. codeBehind="corelib.services.web.webapplications.WebPage">

5. <head>

6. <title>Web component Sample</title>

7. <link rel="stylesheet" type="text/css" href="CssStyles.css" />

8. </head>

9. <body>

10. <h1>Web component Sample</h1> <br />

12. <web:Form>

13. <demo:MyTemplatedComponent readOnly="false" />

14. </web:Form>

16. </body>

17. </web:Html>

VI - Remerciements

Merci à Mickael Baron d'avoir cru en Ellipse Framework, et nous avoir permis de publier nos tutoriels sur « Developpez.com ».

Merci à Mahefasoa pour sa relecture orthographique.

Merci à tous ceux qui font confiance à Ellipse Framework.

L'équipe Ellipse.