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…
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
package
corelib.services.web.samples.virtualcaddy.webcomponents;
import
corelib.services.web.components.WebComponent;
public
class
MinimalComponent extends
WebComponent {
public
MinimalComponent
(
) {
// CAUTION : print a message to the Web server logs
// Not in the HTML result !!!
System.out.println
(
"Hello"
);
}
}
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.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
package
corelib.services.web.samples.virtualcaddy.webcomponents;
import
java.io.PrintWriter;
import
corelib.services.web.components.VisualComponent;
import
corelib.services.web.webapplications.events.WebPageEvent;
public
class
CaddyFooter extends
VisualComponent {
@Override
public
void
component_renderBegin
(
WebPageEvent webPageEvent ) {
PrintWriter out =
this
.webPage.getOut
(
);
out.println
(
"
\n
<hr/>"
);
out.println
(
"<div align='center'>"
);
}
@Override
public
void
component_renderChildren
(
WebPageEvent webPageEvent ) {
PrintWriter out =
this
.webPage.getOut
(
);
out.println
(
" <a href='http://www.infini-software.com'>Ellipse</a>"
);
out.println
(
" sample web application - "
);
out.println
(
" <a href='Trace.wp'>View web trace</a>"
);
}
@Override
public
void
component_renderEnd
(
WebPageEvent webPageEvent ) {
PrintWriter out =
this
.webPage.getOut
(
);
out.println
(
"</div>"
);
}
}
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.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<
web
:
Html
xmlns
:
web
=
"corelib.services.web.components"
xmlns
:
demo
=
"corelib.services.web.samples.virtualcaddy.webcomponents"
codeBehind
=
"corelib.services.web.webapplications.WebPage"
>
<head>
<title>
Web component Sample</title>
<link
rel
=
"stylesheet"
type
=
"text/css"
href
=
"CssStyles.css"
/>
</head>
<body>
<h1>
Web component Sample</h1>
<br />
<
demo
:
CaddyFooter />
</body>
</
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.
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é.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
package
corelib.services.web.samples.virtualcaddy.webcomponents;
import
java.io.PrintWriter;
import
corelib.services.web.components.VisualComponent;
import
corelib.services.web.webapplications.events.WebPageEvent;
public
class
LanguageSelector extends
VisualComponent {
private
String currentLanguage =
"fr"
;
public
String getCurrentLanguage
(
) {
return
currentLanguage;
}
public
void
setCurrentLanguage
(
String currentLanguage ) {
this
.currentLanguage =
currentLanguage;
}
@Override
public
void
component_renderBegin
(
WebPageEvent webPageEvent ) {
PrintWriter out =
this
.webPage.getOut
(
);
String imageStyle =
"style='border: 0px; cursor: pointer;'"
;
out.println
(
"<div>"
);
out.println
(
" <script language='javascript'>"
);
out.println
(
" function changeLanguage( language ) { "
);
out.println
(
" var inputNode = document.getElementById('"
+
this
.getId
(
)+
"');"
);
out.println
(
" inputNode.value = language;"
);
out.println
(
" inputNode.form.submit();"
);
out.println
(
" }"
);
out.println
(
" </script>"
);
out.println
(
" <img src='Images/LocaleFR.png' onclick='changeLanguage(
\"
fr
\"
);'"
);
out.println
(
" title='Changer le language en français' "
+
imageStyle +
"/>"
);
out.println
(
" <img src='Images/LocaleEN.png' onclick='changeLanguage(
\"
en
\"
);'"
);
out.println
(
" title='Change language to english' "
+
imageStyle +
"/>"
);
out.println
(
" <input type='hidden' id='"
+
this
.getId
(
) +
"'"
);
out.println
(
" name='"
+
this
.getId
(
) +
":currentLanguage'"
);
out.println
(
" value='"
+
this
.currentLanguage +
"' />"
);
out.println
(
"</div>"
);
}
}
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.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<
web
:
Html
xmlns
:
web
=
"corelib.services.web.components"
xmlns
:
demo
=
"corelib.services.web.samples.virtualcaddy.webcomponents"
codeBehind
=
"corelib.services.web.webapplications.WebPage"
>
<head>
<title>
User component Sample</title>
<link
rel
=
"stylesheet"
type
=
"text/css"
href
=
"CssStyles.css"
/>
</head>
<body>
<h1>
User component Sample</h1>
<br />
<
demo
:
CaddyFooter />
<
demo
:
LanguageSelector
currentLanguage
=
"fr"
/>
</body>
</
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.
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.
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.
2.
3.
4.
5.
6.
7.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<div
xmlns
:
web
=
"corelib.services.web.components"
style
=
"background: lightGray; border: 1px solid black;"
>
<
web
:
Label
id
=
"lblMessage"
for
=
"txtMessage"
text
=
"Message"
/>
<
web
:
TextBox
id
=
"txtMessage"
/>
<
web
:
Button
id
=
"btnMessage"
/>
<br/>
</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.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
package
com.is.demo;
import
corelib.services.web.components.Button;
import
corelib.services.web.components.Label;
import
corelib.services.web.components.TextBox;
import
corelib.services.web.components.TemplatedComponent;
import
corelib.services.web.webapplications.events.WebPageEvent;
public
class
MyTemplatedComponent extends
TemplatedComponent {
private
Label lblMessage;
private
TextBox txtMessage;
private
Button btnMessage;
public
void
component_load
(
WebPageEvent event ) {
if
(
this
.getWebPage
(
).getRequest
(
).getParameter
(
btnMessage.getId
(
) ) !=
null
) {
System.out.println
(
txtMessage.getValue
(
) +
" entered"
);
}
}
}
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.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<
web
:
Html
xmlns
:
web
=
"corelib.services.web.components"
xmlns
:
demo
=
"com.is.demo"
codeBehind
=
"corelib.services.web.webapplications.WebPage"
>
<head>
<title>
Web component Sample</title>
<link
rel
=
"stylesheet"
type
=
"text/css"
href
=
"CssStyles.css"
/>
</head>
<body>
<h1>
Web component Sample</h1>
<br />
<
web
:
Form>
<
demo
:
MyTemplatedComponent />
</
web
:
Form>
</body>
</
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.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
package
com.is.demo;
import
corelib.services.web.components.Button;
import
corelib.services.web.components.Label;
import
corelib.services.web.components.TextBox;
import
corelib.services.web.components.TemplatedComponent;
import
corelib.services.web.webapplications.events.WebPageEvent;
public
class
MyTemplatedComponent extends
TemplatedComponent {
private
Label lblMessage;
private
TextBox txtMessage;
private
Button btnMessage;
private
boolean
readOnly;
public
boolean
isReadOnly
(
) {
return
this
.readOnly;
}
public
void
setReadOnly
(
boolean
state ) {
this
.readOnly =
state;
}
public
void
component_load
(
WebPageEvent event ) {
this
.txtMessage.setReadOnly
(
this
.readOnly );
if
(
this
.getWebPage
(
).getRequest
(
).getParameter
(
btnMessage.getId
(
) ) !=
null
) {
System.out.println
(
txtMessage.getValue
(
) +
" entered"
);
}
}
}
Pour utiliser ce composant et sa propriété, procédez comme ci-dessous.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<
web
:
Html
xmlns
:
web
=
"corelib.services.web.components"
xmlns
:
demo
=
"com.is.demo"
codeBehind
=
"corelib.services.web.webapplications.WebPage"
>
<head>
<title>
Web component Sample</title>
<link
rel
=
"stylesheet"
type
=
"text/css"
href
=
"CssStyles.css"
/>
</head>
<body>
<h1>
Web component Sample</h1>
<br />
<
web
:
Form>
<
demo
:
MyTemplatedComponent
readOnly
=
"false"
/>
</
web
:
Form>
</body>
</
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.