INSA - ASI TechnoWeb : Struts Technologie Web Unframework J2EE: Struts Alexandre Pauchet INSA Rouen -Département ASI BO.B.RC.18, [email protected] 1/38 INSA - ASI TechnoWeb : Struts Plan 1 Intro duction 2 Fonctionnement 3 Donnéesenprovenanced’un formulaire / d’un lien 4 Couverture d’un formulaire par un Javabean 5 Validation d’unformulaire 6 Conclusion 2/38 INSA - ASI TechnoWeb : Struts (1/6) Intro duction Description Framework développ é par Apache (comme Tomcat) BasésurJ2EE (JSPet servlets): surcouche J2EE, toute appli cation Struts est une application web J2EE Ajoute de nouvelles classes Ajoute de nouveaux tags pour JSP Basé sur l’architecture MVC (Mo dèle-Vue-Contrôleur) Très utilisé 3/38 INSA - ASI TechnoWeb : Struts 4/38 (2/6) Intro duction Le MVC (rap p el) Le Modèle-Vue-Contrôleur (MVC) est une architecture et une mé conception p our le développ ement d’applications logicielles. Le distingue: Mo dèle (données) : le comportement de l’application. Vue (présentation) : interface avecl’utilisateur. Contrôleur (traitement) : gestion des évènementsdesynchro entre la vue et le mo dèle. En résumé, lorsqu’un clientenvoieune requêteà l’application, est ce analysée par le contrôleur, demande qui au mo dèle approprié d’effec lestraitements, puis renvoielavueadaptéeau navigateur,si le mo dèle ne l’apas déjà fait. INSA - ASI TechnoWeb : Struts 5/38 (3/6) Intro duction Le MVC san s Struts Des javab eans (et autres classes) gèrent qui l’asp ect métier (mo d Des JSP (éventuellement sans co de Java) pro qui duisent l’affichage (les vues) Une ouplusieurs Servletsfontlelienentre lesJavaBeansetles JS via lesmécanismesde Délégation/Inlusion(contrôleur(s)) INSA - ASI TechnoWeb : Struts 6/38 (4/6) Fonctionnement L’idée de Struts Ajouter un fichier deconfigurationen XML définissant lesactio gérées par le contrôleur( struts.xml ) Fichier géré par une Servlet sp écifique, définie dans :le web.xml <filter> <filter-name>struts2</filter- name> <filter-class>org.apache.stru ts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</ filter -class> </filter> <filter-mapping> <filter-name>struts2</filter- name> <url-pattern>/*</url-pattern> </filter-mapping> Avantages ⇒ Le co de Java se limite désormais aux aspects métiers ⇒ Beaucoup plus de souplesse : pour changer le comp ortemen l’application,suffit il de changer le co de XML ⇒ Moins de compilation INSA - ASI TechnoWeb : Struts 7/38 (5/6) Intro duction Installation Installation 1 Récupérer une archive (comprise struts2-blan k-VERSION.war dansles exemples d’application) sur http://stru ts.apache.org/ . Versions :1.3.10 ou 2.2.1 2 La copier dans :elle se décompresse touteseule, comm webapps tout fichier .war 3 OnaalorsuneapplicationStruts vide ⇒ Pour créerune nouvelleapplication,on copie , on le renomme, et on effectue les struts2-bla nk-VERSION.war mo difications à l’intérieur. INSA - ASI TechnoWeb : Struts (6/6) Intro duction Contenu (p artiel) de struts-blank struts-blan k-2.2.1.war |_ index.html |_ example | |_ Welcome.jsp, ... |_ WEB_INF | |_ web.xml | |_ src | | |_ java | | |_ ... | |_ lib | | |_ struts2-core-2.2.1.jar, ... | |_ classes | |_ struts.xml,... |_ META-INF |_ MANIFEST.MF, ... 8/38 INSA - ASI TechnoWeb : Struts 9/38 (1/6) Fonctionnement Fonctionnement d’une app lication Struts L’utilisateur app elle (formulaire, lien, etc.) une URL de la fo traitement .action,traitée selon le contenude struts.xml On appelle la méthoexecute de d’uneinstancedérivée de laclasse : ActionSupp ort publicString execute() throwsException {...} Une JSP est appelée en fonction du résultat de la métho de e struts.xml INSA - ASI TechnoWeb : Struts 10/38 (2/6) Fonctionnement Exemple :HelloWorld index.jsp <%@ page languag e="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefi x="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://ww w.w3.org/TR/html4/loose.dtd"> <html> <head > <meta http-equiv="Content-Type" content ="text/html; charset=IS O-8859-1"> <title>Basic Struts 2 Application - Welcome</ title> </head > <b o dy > <h1>Welcome To Struts 2!</h1> a href="<s:url action=’hello’/>" >Hello World</a></p> <p>< </b ody > </html> INSA - ASI TechnoWeb : Struts (3/6) Fonctionnement Exemple :HelloWorld struts.xml <?xml version ="1.0" encoding="UTF -8"?> <!DOCTYPE struts PUBLIC "-//ApacheSoftware Foundation//DTDStruts Configuration 2.0//EN" "http://struts.apache.org /dtds/struts-2.0.dtd"> <struts> <constant name="struts.dev Mode" value="true" /> <package name="basicstruts 2" extends="struts-default"> <!-- If no cla ss attribute is specified the framework will assume success an d render the result index .jsp --> default--> <!-- If no nam e value for the result node is specified the success val ue is the <action name="index"> <result>/index.jsp</result> </action> <!-- If the UR L is hello.action the call t he execute method of class H elloWorldAction. If the result returned by the execute meth od is success render the Hel loWorld.jsp --> <action name="hello" class="helloworld.action.HelloWorldAction" method="execute"> <result name="success"> /HelloWorld.jsp</result> </action> </package> </struts> 11/38 INSA - ASI TechnoWeb : Struts (4/6) Fonctionnement Exemple :HelloWorld HelloWordAction.java packagehelloworld.action; imp orthelloworld.model.StringMe ssage; imp ortcom.opensymphony.xwork2.A ctionSupport; public classHelloWorldAction extendsActionSupport{ privatestatic final long serialVersionUID = 1L; privateStringMessage message; publicString execute() throwsException{ this.message= new StringMessage("Hello World !"); returnSUCCESS; } publicStringMessage getSt ringMessage(){ return this .message; } public voidsetStringMessage(StringMe ssage message){ this.message = message; } } 12/38 INSA - ASI (5/6) Fonctionnement Exemple :HelloWorld StringMessage.java packagehelloworld.model; public classStringMessage{ privateString message; publicStringMessage(String message){ this.setMessage(message); } publicString getMessage(){ returnmessage; } public voidsetMessage(String message){ this.message = message; } } TechnoWeb : Struts 13/38 INSA - ASI TechnoWeb : Struts 14/38 (6/6) Fonctionnement Exemple :HelloWorld HelloWorld.jsp <%@ page languag e="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefi x="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://ww w.w3.org/TR/html4/loose.dtd"> <html> <head > <meta http-equiv="Content-Type" content ="text/html; charset=IS O-8859-1"> <title>Hello World!</title> </head > <b o dy > s:property value <h2>< ="stringMessage.message" />h2 </> </b ody > </html> INSA - ASI TechnoWeb : Struts 15/38 Données en provenance d’un formulaire /(1/6) d’un lie Fonctionnement Utilisation de javab eans L’utilisateur remplit(parexemple)unformulaireissud’uneJSP o d’un do cument HTML statique On app elle lors de la validation une URL de la forme traitement. action,qui est traitée en fonctionducontenu de struts.xml On appelle la méthoexecute de d’uneinstancedérivée de laclasse ActionSuppo rt La classe app elée doit se présenter sous la forme d’u javab ean dont les propriétés (getter et setter) vont corresp ondre aux champs du formulaire Une JSP est appelée en fonction du résultat de la métho de e struts.xml INSA - ASI TechnoWeb : Struts 16/38 Données en provenance d’un formulaire /(2/6) d’un lie Exemple :HelloWorldPost index.jsp <%@page contentType="t ext/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HT ML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd "> <%@taglib uri="/struts -tags" prefix="s" %> <html> <head > <meta http-equiv="Content-Type" content ="text/html; charset =UTF-8"> <title>Hello World Post</title> </head > <b o dy > <s:url action ="hello" var="helloLink"> s: param <s: param name ="userName">Bob Leponge</ > </s:url> a href="${helloLink}">Hello Bo b Leponge</ a></p> <p>< <s: form action ="hello"> lab el <s:textfield name ="userName" ="User Name" /> s < :submit /> </s: form> </b o dy > </html> INSA - ASI TechnoWeb : Struts 17/38 Données en provenance d’un formulaire /(3/6) d’un lie Exemple :HelloWorldPost struts.xml <!DOCTYPE struts PUBLIC "-//Apache Software Fo undation//DTD Struts Configuration 2.0//EN" "http:// struts.apache.org/dtds/st ruts-2.0.dtd"> <struts> <package name="defau lt" extends="struts-default"> <action name="hello" class="helloworldpost.action.HelloWorldPostAction" method="execute"> <result name="success">/ success.jsp</result> </action> </package> </struts> INSA - ASI TechnoWeb : Struts 18/38 Données en provenance d’un formulaire /(4/6) d’un lie Exemple :HelloWorldPost HelloWordPostAction.java packagehelloworldpost.action; imp orthelloworldpost.model.User Name; imp ortcom.opensymphony.xwork2.A ctionSupport; public classHelloWorldPostAction extendsActionSupport{ privatestatic final long serialVersionUID = 1L; privateUserName userName; privateString message; publicString execute() throwsException{ this.message = "Hello "+ this.getUserName() +" !"; returnSUCCESS; } publicString getMessage(){ return this .message; } publicString getUserName(){ return this .userName.getName(); } public voidsetUserName(String userName){ this.userName= new UserName(userName); } } INSA - ASI TechnoWeb : Struts 19/38 Données en provenance d’un formulaire /(5/6) d’un lie Exemple :HelloWorldPost UserName.java packagehelloworldpost.model; public classUserName{ privateString name; publicUserName(String na me){ this.setName(name); } publicStringgetName(){ return this .name; } } public voidsetName(String name ){ this.name = name; } INSA - ASI TechnoWeb : Struts 20/38 Données en provenance d’un formulaire /(6/6) d’un lie Exemple :HelloWorldPost success.jsp <%@page contentType="t ext/html" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HT ML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd "> <%@taglib uri="/struts -tags" prefix="s" %> <html> <head > <meta http-equiv="Content-Type" content ="text/html; charset =UTF-8"> title < >Hello World</title> </head > <b o dy > s:property value h1> <h1>< ="message" /></ </b o dy > </html> INSA - ASI TechnoWeb : Struts 21/38 (1/9) ean Couverture d’un formulaire par un Javab Principe Principe Les propriétés d’un Javab ean sont utilisées pour encapsuler valeurs d’un formulaire Des tags Struts 2 sont utilisés pour lier champs et propriétés Les tags Struts 2 sont interprétés p our générer du co de HT ⇒ Dansstruts.xml , une métho de doit être définie pour force filtre et parser les tags Certains tags (listes, radio buttons, etc.) nécessitent une ini INSA - ASI TechnoWeb : Struts 22/38 (2/9) ean Couverture d’un formulaire par un Javab Exemple : Javab ean index.jsp <%@ page languag e="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefi x="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://ww w.w3.org/TR/html4/loose.dtd"> <html> <head > <meta http-equiv="Content-Type" content ="text/html; charset=IS O-8859-1"> title> <title>Struts 2 Form Tags - Welcome</ </head > <b o dy > <h1>Welcome To Struts 2!</h1> a href=’<s:url action <p>< ="edit" />’ >Edit your information</ a></p> </b ody > </html> INSA - ASI TechnoWeb : Struts (3/9) ean Couverture d’un formulaire par un Javab Exemple : Javab ean struts.xml <?xml version ="1.0" encoding="UTF -8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Fo undation//DTD Struts Configuration 2.0//EN" "http:// struts.apache.org/dtds/st ruts-2.0.dtd"> <struts> <constant name="struts.de vMode" value="true" /> <package name="basicstrut s2" extends="struts-default"> <!-- If no cla ss attribute is specified the framework will assume success a nd render the result index .jsp --> default--> <!-- If no nam e value for the result node is specified the success val ue is the <action name="index"> <result>/index.jsp</result> </action> <action name="edit" class="register.action.Register" method="inp ut"> <result name="input">/e dit.jsp</result> </action> <action name="regist er" class="register.action.Register" method= "execute"> <result name="success"> /thankyou.jsp</result> </action> </package> </struts> 23/38 INSA - ASI TechnoWeb : Struts 24/38 (4/9) ean Couverture d’un formulaire par un Javab Exemple : Javab ean edit.jsp <%@ page languag e="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefi x="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://ww w.w3.org/TR/html4/loose.dtd"> <html> <head > <meta http-equiv="Content-Type" content ="text/html; charset=IS O-8859-1"> <title>Basic Struts 2 Application - Welcome</ title> </head > <b o dy > <h1>Welcome To Struts 2!</h1> p> <p>Fillout and submitthe following form:</ <s: form action ="register"> <s:textfield name ="personBean.firstName"lab el ="First name" /> lab el <s:textfield name ="personBean.lastName" ="Last name" /> <s:textfield name ="personBean.email"lab el="Email"/> lab el="Gender" list="gen ders" /> <s:radio key="personBea n.gender" <s: selectkey="personBean.sport"lab el="Sport" list="sports " /> lab el <s:checkbox key="person Bean.over21" ="Over 21" /> <s:submit value ="Submit" /> s form </ : > </b ody > </html> INSA - ASI TechnoWeb : Struts (5/9) ean Couverture d’un formulaire par un Javab Exemple : Javab ean Register.java packageregister.action; imp imp imp imp imp ortjava.util.ArrayList; ortjava.util.Arrays; ortjava.util.List; ortregister.model.Person; ortcom.opensymphony.xwork2.A ctionSupport; public classRegister extendsActionSupport{ privatestatic final long serialVersionUID = 1L; privatePerson personBean; privateString [] sports = {"football", "volleyball", "basket ball"}; privateString[]genders = {"male","female"}; publicString execute() throwsException{ returnSUCCESS; } publicString input() returnINPUT; throwsException{ } publicPerson getPersonBea n(){ returnpersonBean; } . .. 25/38 INSA - ASI TechnoWeb : Struts (6/9) ean Couverture d’un formulaire par un Javab Exemple : Javab ean Register.java . .. public voidsetPersonBean(Person person){ personBean = person; } publicList<String> getSpo rts(){ returnArrays.asList(sports); } publicList<String> getGen ders(){ returnArrays.asList(genders); } } 26/38 INSA - ASI TechnoWeb : Struts (7/9) ean Couverture d’un formulaire par un Javab Exemple : Javab ean Person.java packageregister.model; public classPerson { privateString firstName; privateString lastName; privateString email; privateString gender; private bo olean over21; privateString sport; publicStringgetFirstName(){ returnfirstName;} public voidsetFirstName(String firstNa me){ this.firstName = firstNa me;} publicStringgetLastName(){ returnlastName;} public voidsetLastName(String lastName ){this.lastName = lastN ame;} publicString getEmail(){ returnemail;} public voidsetEmail(String email){ this.email =email;} . .. 27/38 INSA - ASI TechnoWeb : Struts (8/9) ean Couverture d’un formulaire par un Javab Exemple : Javab ean Person.java . .. public voidsetGender(String gen der){ this.gender = gender;} publicStringgetGender(){ returngender;} public voidsetOver21(b o olean over21){ this.over21 = over21;} public bo olean isOver21(){ returnover21;} publicStringgetSport(){ returnsport;} public voidsetSport(String spo rt){ this.sport =sport;} } publicStringtoString(){ String desc = getFirstName() + " " + getLastName() + ", " + getE mail() + ", " + getGender() + ", joueur de "+ getSport(); if(over21) desc += ", majeur"; else desc += ", mineur"; returndesc; } 28/38 INSA - ASI TechnoWeb : Struts 29/38 (9/9) ean Couverture d’un formulaire par un Javab Exemple : Javab ean thankyou.jsp <?xml version="1.0" encoding="ISO-8859-1" ?> <%@ taglib prefi x="s" uri="/struts-tags" %> <%@ page languag e="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww w.w3.org/TR/xhtml1/DTD/xhtml1 -transitional.dtd"> <html xmlns ="http://www.w3.org/1999 /xhtml"> <head > <meta http-equiv="Content-Type" content ="text/html; charset=IS O-8859-1" /> <title>Registration Success ful</title> </head > <b o dy > <h3>Thank you fo r registering !</ h3> p> <p>Yourregistration information:< s:property value ="personBean" /> </ a href="<s:url action=’edit’ />" >Return to home page</a>.</p> <p>< </b ody > </html> INSA - ASI TechnoWeb : Struts 30/38 (1/6) Validation d’un formulaire Principe Validation de formulaire en utilisa nt Struts2 Utiliser les résultats de la métho de de traitement d’un form pour choisir la vue: Le contrôle est défini dansstruts.xml Lestests sonteffectués dans le contrôleur Faciliter les messagesd’erreursenutilisant lestagsStruts2 Attention : validation côté serveurnécessitant égalem validation côté utilisateur INSA - ASI TechnoWeb : Struts 31/38 (2/6) Validation d’un formulaire Exemple :Validation index.jsp <?xml version="1.0" encoding="ISO-8859-1" ?> <%@ taglib prefi x="s" uri="/struts-tags" %> <%@ page languag e="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww w.w3.org/TR/xhtml1/DTD/xhtml1 -transitional.dtd"> <html xmlns ="http://www.w3.org/1999 /xhtml"> <head > meta < http-equiv="Content-Type" content ="text/html; charset=IS O-8859-1" /> <title>Register</title> <s: head/><!-- Nécessaire pour afficher les erreurs !--> </head > <b o dy > <h3>Please register</ h3> <s: form action ="register"> <s:textfield name ="personBean.firstName"lab el ="First name" /> lab el <s:textfield name ="personBean.lastName" ="Last name" /> <s:textfield name ="personBean.email"lab el="Email"/> <s:textfield name ="personBean.age"lab el ="Age" /> <s:submit/> </s: form> </b ody > </html> INSA - ASI TechnoWeb : Struts (3/6) Validation d’un formulaire Exemple :Validation struts.xml <?xml version ="1.0" encoding="UTF -8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Fo undation//DTD Struts Configuration 2.0//EN" "http:// struts.apache.org/dtds/st ruts-2.0.dtd"> <struts> <constant name="struts.de vMode" value="true" /> <package name="basicstrut s2" extends="struts-default"> <!-- If no cla ss attribute is specified the framework will assume success a nd render the result index .jsp --> default--> <!-- If no nam e value for the result node is specified the success val ue is the <action name="index"> <result>/index.jsp</result> </action> <action name="regist er" class="register.action.Register" method= "execute"> <result name="success"> /thankyou.jsp</result> <result name="input">/i ndex.jsp</result> </action> </package> </struts> 32/38 INSA - ASI TechnoWeb : Struts (4/6) Validation d’un formulaire Exemple :Validation Register.java packageregister.action; imp ortregister.model.Person; imp ortcom.opensymphony.xwork2.A ctionSupport; public classRegister extendsActionSupport{ privatestatic final long serialVersionUID = 1L; privatePerson personBean; publicString execute() throwsException{ returnSUCCESS;} public voidvalidate(){ if ( personBean.getFirstName ().length() == 0 ){ addFieldError( "personBean.firstName", "First name is req uired." ); } if ( personBean.getEmail().l ength() == 0 ){ addFieldError( "personB ean.email", "Email is required." ); } if ( personBean.getAge() < 18){ addFieldError( "personB ean.age", "Age is required and must be 18 or older" ); } } } publicPerson getPersonBea n(){ return this .personBean;} public voidsetPersonBean(Person person){ this.personBean = pers on;} 33/38 INSA - ASI TechnoWeb : Struts (5/6) Validation d’un formulaire Exemple :Validation Person.java packageregister.model; public classPerson { privateString firstName; privateString lastName; privateString email; private intage; publicStringgetFirstName(){ returnfirstName;} public voidsetFirstName(String firstName){ this.firstName = firstNam e;} publicString getLastName(){ returnlastName;} public voidsetLastName(String lastName){ this.lastName = lastN ame;} publicString getEmail(){ returnemail;} public voidsetEmail(String em ail){ this.email =email;} public intgetAge(){ returnage;} public voidsetAge(int age){ this.age =age;} } publicString toString(){ returngetFirstName() + ""+ getLastName()+ ", "+getEmail()+ ", " + getAge() +" ans"; } 34/38 INSA - ASI TechnoWeb : Struts 35/38 (6/6) Validation d’un formulaire Exemple :Validation thankyou.jsp <?xml version="1.0" encoding="ISO-8859-1" ?> <%@ taglib prefi x="s" uri="/struts-tags" %> <%@ page languag e="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww w.w3.org/TR/xhtml1/DTD/xhtml1 -transitional.dtd"> <html xmlns ="http://www.w3.org/1999/xht ml"> head < > <meta http-equiv="Content-Type" content ="text/html; charset=IS O-8859-1" /> <title>Registration Successful</ title> </head > <b o dy > p> <p>Registration informat ion:< s:property value ="personBean" /> </ a href="<s:url action=’index’ />" >Return to home page</ a>.</p> <p>< </b ody > </html> INSA - ASI TechnoWeb : Struts 36/38 (1/3) Conclusion Struts? Et le reste? Strutsn’estpas le seul outilde haut niveau disp onible pour les applications web J2EE: Java Server Faces (JSF), Tap estry, Hib ernate, Spring (Spring MVC), ... Ces outilsne sontpasmutuellementexclusifs: Struts est plutôt sp écialisé "contrôleur" JSF prop ose des composants graphiques : "vue" Hib ernate, les EJB et autres s’intéressent à la sérialisation d objets : "mo dèle" INSA - ASI TechnoWeb : Struts 37/38 (2/3) Conclusion Fau t-ilutiliser Struts? Oui si l’application est conséquente; Non s’ils’agit d’uneapplicationsimple (exemplelimite, leblog) mêmele site de Struts déconseilled’utiliserle Frameworkdan cas-là On peut utiliser des JSP seules, du PHP ou un framework dit (Ruby onRails,Django,...)dans les cas plus simples INSA - ASI TechnoWeb : Struts (3/3) Conclusion Sources http: //struts.apache.org/ http: //www-lih.univ-lehavre.fr/~co letta/dess0607/struts/une_appli.html http: //www-lih.univ-lehavre.fr/~co letta/dess0607/struts/erreurs.html http: //www.labo-sun.com/resource-f r-essentiels-859-5-java-j2ee-struts-un-framework-mvc-pou r-vosapplications-j2ee.htm\#h1n3 http: //www.jmdoudoux.fr/java/dej/c hap052.htm 38/38