Documents > J2SE APIs > J2EE APIs

Slides:



Advertisements
Présentations similaires
- Formation STRUTS 1 1.
Advertisements

Présentation de frameworks J2EE
HTML la base Structure de la page Code HTML: les tags de base.
JEE 5 - JSF F.Pfister 2 institut eerie Les technologies du web Servlets JSP MVC Model 1 : servlets + JSP MVC Model.
Internet et le client- serveur Licence Pro IE Cours Internet / Intranet Le Web HTML Protocoles Le client universel Contenus dynamiques.
Cours 5 : XML et les architectures N-tier Janvier Version 1.0 -
ASP.NET v2 + Ajax = Atlas Pierre Lagarde DevDays 2006 Equipé aujourdhui, prêt pour demain !
Architecture Technique de la plate-forme CASTORE
Stage serveur web sémantique
Serveurs web pour JSP et Servlets
AWEB Gestion d’un théâtre 28 juin 2002
Toolkit Web Framework Java pour les IHMs Cédric Dumas mars 2008 contrat Creative Commons Paternité-Pas d'Utilisation Commerciale- Partage.
Architecture Technique de la plate-forme CASTOR Projet Castor © Ecole des Mines de Nantes
CURSUS DE FORMATION AUX NOUVELLES TECHNOLOGIES DE DEVELOPPEMENT UV Borland JBuilder 7 Module WSAD.
Gestion de ProjetTP ©Yossi Gal, Oct/2005TP, Page: 1 Le sujet Proposé Construire une application e-commerce qui permet d effectuer un achat on-line Lorganisation.
16/10/10 Préparé par: Ing. Rodrigue Osirus (+509) , *** Site web dynamique.
Introduction aux services WEB
PROJET HANDICAPS Certificat de Qualification Professionnelle
LOG 02 Bases de Données Avancées Rappels sur JSP / Servlet
2006/2007Denis Cabasson – Programmation Web Cours de programmation web ENSAE
OPTIMALJ, CONCEPTION ET DÉVELOPPEMENT RAPIDE MDA-PATTERNS-UML EJB 2
Portfolio - Dossier de cheminement Techniques de linformatique Rivière-du-Loup.
Serveurs d’application
A. Roussanaly - Université Nancy2 AXIS Master MIAGE/SID – Université NANCY2.
Architectures Web - N-Tiers
TomCat M2 – MIAGE/SID
Cours GLG203 Cours J2EE JDBC, RMI, IIOP, Sécurité, XML
Archimède : dépôt institutionnel de la Bibliothèque de lUniversité Laval Par Rida Benjelloun Chef de la section recherche.
Identifier ce qui peut gêner ou bloquer votre référencement Sébastien Billard, consultant référencement.
Normandy JUG Présentation de JSF.
Projet JAVA EE Approfondi
PROJET DE GENIE LOGICIEL 2005
I.S.I.S. Information System Initial Specification Rétro-conception de Bases de données Cyr Gabin Bassolet TIMC – équipe OSIRIS 21 décembre 2004.
JSP (Java Server Pages)
Les Serveurs WEB.
MODEX WEB DOMINIQUE ROSSIN Mysql. La semaine passée index.php?page=contact Page autorisée ? Redirection NON
Michel Coletta - Journées PATTERNS Avril Grenoble1 STRUTS Introduction Technologies Java Architecture Développement Enseigner quoi ?
J2EE vs .NET Réaliser par : SEIF ENNACER BADRA && CHETOUI RIM.
Initiation au web dynamique - TP
JEE 5 F.Pfister 2 institut eerie JEE – Une plateforme serveur  Développement et exécution d'applications réparties.
M2 – MIAGE/SID Servlet M2 – MIAGE/SID
GWT - QuickStart V 1.0 / May. Mise en place de l’environnement Java : Version 1.4 minimum IDE Eclipse 3.3 Europa : lien (Eclipse J2EE recommandée)‏lien.
1 - Architecture Internet
Internet et le client- serveur Licence Pro IE Cours Internet / Intranet Le Web HTML Protocoles Le client universel Contenus dynamiques.
Module I-C3 : Applications Web IUT R&T 2e année
Java Enterprise Edition, anciennement J2EE
eVinci-XP | Portail de services
Mise en place d’un Intranet
Conférence Technique Java 2 Frédéric Jacquet. Au programme  Présenter les différents outils  Découverte - Java coté serveur  Appréhender l ’existant.
Présentation du framework JSF (Java Server Faces) dans le modèle événementiel MVCII
Struts.
PHP SpeedBerg Templates EPFL PHP IIème Conférence des WebMasters EPFL 5/12/2001 Tuan Lam E-PFL
Conférence Témoignages métiers- Supinfo Nantes  Création en 1979  CA de 150 Millions €  Présence nationale et internationale  2300 personnes en France.
Rapport de Stage : Les Web Services ou la communication
Séance /10/2005 CSS et Dreamweaver. CSS : principes Cascading Style Sheet = feuille de style en cascade Norme du W3C :
Séance /01/2006 Les technologies des sites dynamiques.
13/07/2015 JSF Java Server Faces Master 2 Pro GLR TER David Mihura Eric Le Merdy.
Cursus Formation Jean-Marc Vanel Formations développement logiciel, du débutant à l'expert.
Simplifier et assurer la traçabilité des apports ou demandes extérieures sur plusieurs flux de déchets Service informatique Thau agglo
{ Java Server Pages Par Billy et Mike.  Introduction  Qu’est-ce que JSP?  Pourquoi utiliser JSP?  Développement  Balises  Servlets  Conclusion.
Architectures Logicielles Java GLG203 GLG204
Parquet Geoffrey 3 ARIL EXIA.CESI ARRAS. Présentation du MLD Présentation de la persistance Présentation récapitulatif du projet JSP/SERVLET MVC Cycle.
Architecture J2EE Web Jean-Jacques LE COZ. J2EE Web Container JSP Page Servlet J ava 2 Standard Edition APIs EJB Container EJB JDBCJMS JNDI JTA JavaMail.
Présentation Projet JEE Présentation des Frameworks Java Server Faces & Eclipse Link.
Apache Tomcat Distributeur : Apache Software Foundation Projet : Jakarta Catégorie : Serveur d'applications Technologie : Java.
Java – Réseau Eric Blaudez 06.
TITRE CONTENU.
SRT2 APACHE.
Architectures Logicielles Java GLG203 GLG204
Transcription de la présentation:

Documents http://ltiwww.epfl.ch/ProgrammationInternet > J2SE APIs > J2EE APIs http://ltiwww.epfl.ch/WebLang >  Bibliographical references > Description of All Components

Applications Web 1 Appel d’une page HTML (browser/telnet), appel d’une servlette (telnet, FORM) Création/appel d’une servlette en WebLang, en WTP 2 La servlette affiche un lien sur le fichier de la FORM. Elle affiche la FORM elle-même. utilisation de sendRedirect 3 Passage des données par String, par Java bean. <Usebean>. Source JSP. Une seule JSP pour le tout. 4 Créer un CMP bean. Voir dans Hypersonic. Initialiser au moyen d’une servlette. 5 Relation pays – ville – capitale. Connecter les composants. Mettre le code dans des session beans. 6 Session bean retournant une collection provenant d’une relation. Parcours de cette relation dans une servlette 7 Villes d’un pays, pays d’une capitale, pays d’une ville. Effacement d’une ville. Remplissage au moyen de ant 8 Test 9 Liste de villes dans un rich client. Client avec un topic. Diffusion de messages. Jeu papier-caillou-ciseaux. 10 Jeu sur une FSM. 11 Struts: bibliothèque. 12 Struts: enregistrement des utilisateurs vérifiés par un manager 13 Test

J2EE Java php Websphere CVS Weblogic Visual Age .net ant RMI Eclipse JDO Hybernate Java J2EE MySQL Javascript HTML Entity Bean JSF Servlet Cookie XML JBoss JSP MDBean taglib Tomcat http://www.topjobs.ch/ Struts Rechercher: J2EE, PHP, Apache

LAMP (pas présenté) DB Linux, Apache, MySQL, PHP Server Client Network Browser DB PHP <html>  <head>   <title>Test PHP</title>  </head>  <body>  <?php echo ‘Bonjour '; ?> </body> </html> Network

Application Web sur J2EE Tomcat JBoss Server Session EJB DB Client proxy Browser Entity EJB proxy Servlet Entity EJB x.html proxy Network

Pages HTML et Servlettes Livre Software Engineering Sections 7.5, 7.7

Page HTML <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>     <head>         <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>         <title>Tests/test</title>         <script type="text/javascript">          function init() { // Javascript              alert("Bonjour")          }        </script>     </head>     <body onload="init()"> Contenu de la page     </body> </html>

Elements HTML         <h1>Un grand titre</h1>         <p>Un paragraphe</p>         <table cellspacing="6" cellpadding="6"  border="1" bgcolor="yellow">             <tr>                 <td bgcolor="#FFE0E0"> ligne1 <br>  colonne 1</td>                 <td bgcolor="#E0E0FF"> ligne1, colonne 2</td>             </tr>         </table>

Elements actifs dans une form         <form method="get" name="record" action="http://localhost:8080/xxxx">             <input type="text" name="txInput1"/> <br>             <input type="text" name="txInput2" value="initial"/>             <input type="button" name="something" value="button"/>             <input type="checkbox" name="checkB1" value="aaa"/>AAA             <input type="checkbox" name="checkB2" value="bbb"/>BBB             <input type="radio" name="radioB" value="ccc"/>CCC             <input type="radio" name="radioB" value="ddd"/>DDD

Sélections             <p>                 <select name="simpleSelection">                     <option value="eee">EEE                     </option>                     <option value="fff">FFF                     </option>                 </select>             </p>             <p>                 <select multiple name="multipleSelection">                     <option value="hhh">HHH                     </option>                     <option value="jjj">JJJ                     </option>                 </select>             </p>

Autres éléments             <p><input type="hidden" name="myValue" value="not_seen"/>             </p>             <p>                 <textarea name="thetext" rows="8" cols="80">                     ha ! ha ! ha !                 </textarea>             </p>             <p>                 <button name="button" value="button" type="button"/> Click<br>                  <img width="100" src="green.gif“ alt="wow"> </button>             </p>             <p><input type="submit" name="button"/>  <input type="reset"/>             </p>         </form>

Form Envoyé au serveur (une seule ligne)        <form method="get" name="record" action="http://localhost:8080/xxxx"> . . . elements des pages précédentes . . .         </form> Envoyé au serveur (une seule ligne) http://localhost:8080/xxxx?txInput1= &txInput2=initial &simpleSelection=eee &myValue=not_seen &thetext=+++++ha+!+ha+!+ha+!%0D%0A++ &button=Envoyer

Upload de fichiers <form method="post" name="upform" action="http://localhost:8080/check"              enctype="multipart/form-data">             <input type="file" name="uploading"/>             <input type="submit"/>         </form>

Accès au serveur HTML Browser (client) Tomcat, Apache . . . (serveur) HTML: Test.html <A HREF="URL">link</a> Internet

Servlet Objet généralisé Possède une méthode doGet Serveur Web Browser Servlet doGet() { … } URL avec paramètres Objet généralisé Possède une méthode doGet Est exécuté dans un serveur Web Appelé par un browser

Servlet qui lit les données entrées dans des champs Bouton submit

Formulaire HTML <form action=“http://localhost:8080/test"> <input type=“submit” name=“add“> <input type=“text” name=“val"> </form>

Formulaire HTML (Paragraphe 7.5.2) <form action=“http://localhost:8080/test"> add: <input type=“submit” name=“add"> <p> val: <input type=“text” name=“val"> </form>

Appeler une servlette Browser Serveur JBoss servlet: Test.java HTML page <form action="URL"> <input type = "text" name="field"> </form> servlet: Test.java Internet Exécution de Java page HTML

Servlette: traitement des données public class Test extends HttpServlet { public void doGet ( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException { PrintWriter out = response.getWriter(); response.setContentType("text/html"); out.println ("<html><body>"); out.println ("<h1>Title</h1></body>"); } Javadoc J2EE La page html est produite automatiquement quand la méthode se termine.

Classes Http Servlet HttpServletRequest.html, ServletRequest.html HttpServletResponse.html, ServletResponse.html HttpSession.html

Décodage d’un paramètre dans une servlette (voir J2EE Javadoc) <form action="http:www.epfl.ch/servletName//"> http://www.epfl.ch/servletName?txtInp=yyy <input type = text name = "txtInp"> Servlette yyy

Décodage d’un paramètre dans une servlette (voir J2EE Javadoc) Navigateur http://www.epfl.ch/servletName?txtInp=yyy valueParam = request.getParameter("txtInp"); dans la servlette valueParam.equals("yyy") Java

Production du contenu d’une page HTML par une servlette java.io.PrintWriter out = response.getWriter(); out.println(“<h1>Titre</h1>”);

WebLang Crée les sources des composants, les fichiers auxiliaires et les fichiers ant

Fichier .cg http://ltiwww.epfl.ch/WebLang/Modules.html#servlets @@deploypath="C:/jboss-4.2.3.GA/server/default/deploy/" servlet SomeServlet { package servletPack; public void someCall (PrintWriter out, String name, double number) { out.println(name + " " + number); }

Module servlet en WebLang servlet TestServlet { package packageName; int attribute; // dangereux public void add ( PrintWriter out, int number) { attribute += number; out.println(attribute); } public void sub (int number) { attribute = number; determine la form HTML

WebLang génère les fichiers: html: InputForms <FORM action= "test"> a b m1 c m2 servlet: Test.java doGet() { . . . } m1(int a, String b) { ... } m2(String c, long d) { ... }

Avec plus de détails html: InputForms servlette: Test.java <form action= "test"> <input ... name="a"> <input ... name="b"> <submit name="m1"> </form> <input ... name="c"> <submit name="m2"> servlette: Test.java doGet() { a = getParameters(“a”); m1(a, b); or m2(c, d); } m1(int a, String b) { ... } m2(String c, long d) { ... }

Préparation et chargement d’une servlette Eclipse fichier.cg CodeGen myServlet.java @web doGet() { } xdoclet packaging web.xml projet.ear WebLang Navigateur Serveur web.xml myServlet.java myPage.html

Compilation d’un fichier.cg bouton droit de la souris Compilation d’un fichier.cg

Déploiement d’un projet WebLang Run As… > CGxdoclet.xml Run As… > CGpackaging.xml

Démarrer le serveur JBoss Il est possible de gérer le serveur JBoss, ou d’autres serveurs à partir d’Eclipse. Les manipulations de préparation sont présentées ci-dessous. Ces manipulations préparent en même temps les librairies nécessaires aux projets J2EE http://ltiwww.epfl.ch/WebLang/JBossInit

Nettoyer les programmes dans JBoss Eliminez les programmes et structures laissés par l'étudiant précédent. Pensez à le faire dans les leçons suivantes également ! Effacez les répertoires tmp, data, log et work qui se trouvent dans C:\jboss-4.2.3.GA\server\default Effacez tous les fichiers se terminant par .ear (pour archive) ou .war se trouvant dans C:\jboss-4.2.3.GA\server\default\deploy Pour arrêter JBoss, cliquer le carré rouge dans la fenêtre serveur et attendez qu’il se termine!

Singleton (pour l’exercice) Une seule instanciation, à la première utilisation. public class BD { private static BD localBD = null; public static BD getBD() { if (localBD==null) { localBD = new BD(); } return localBD; private String name; // autres paramètres // utilisation BD.getBD().list();

Définition d’une classe en WebLang class MyClass { package aPackage; import java.util; access remote; // optional, default is local outputchannel myCh (queue, A); // future Bean bean; public void aMethod() throws Exception { System.out.println("a method called"); Bean b = beanHome.create(); // future b.method(); } Génère une classe habituelle et introduit les références et fonctions qui permettront de la charger dans le serveur.

Affichage pour dépanner System.out.print(“xxx”); affiche ses sorties dans la console d’Eclipse

Exercice 1: une application Web nom incorrect Servlet login() cancel() Page HTML entrée Singleton (à la place d’une base de données) correct Servlet store(String x) list() quit() Page HTML entrée transition entre états introduction de données

Structure et scripts d’un projet JEE

Structure d’un projet JEE servlets librairies JEE fichier d’appel de tous les objets générés fichiers d’appel des méthodes des servlets JSP définition des servlets scripts ant de préparation tout est génére à partir de ce fichier

xDoclets Outil standard pour créer une partie des fichiers indiqués dans les pages précé- dentes http://xdoclet.sourceforge.net/xdoclet/index.html

xDoclet crée le fichier web.xml import javax.rmi.PortableRemoteObject; . . . /** * @web.servlet * name = "MyServletServlet" * display-name = "TestServlet" * description = "A simple Servlet" * @web.servlet-mapping * url-pattern = "/MyServlet" */ public class TestServlet extends HttpServlet { public void doGet (HttpServletRequest request,

Script ant pour appeler XDoclet généré automatiquement par WebLang <?xml version="1.0" encoding="UTF-8" ?> <project default="N2" name="XDoclet Generator"> <path id="xdoclet.classpath"> <pathelement location="C:/jboss-4.0.4.GA/server/default/lib/javax.servlet.jar"/> <fileset dir="C:\eclipse\xdoclet_lib/"> <include name="*.jar" /> </fileset> </path> <target name="N2" description="Servlet/Taglib"> <taskdef classpathref="xdoclet.classpath“ classname="xdoclet.modules.web.WebDocletTask“ name="webdoclet" /> <webdoclet destDir="WEB-INF" verbose="true" mergeDir="WEB-INF/merge"> <fileset dir="src"> <include name="package/AServlet.java" /> <deploymentdescriptor Servletspec="2.3" /> </webdoclet> </target> </project>

Contenu de web.xml généré automatiquement par xdoclet <servlet> <servlet-name>MyServletServlet</servlet-name> <display-name>MyServlet</display-name> <description><![CDATA[A simple Servlet]]></description> <servlet-class>serv.MyServlet</servlet-class> </servlet> <servlet-mapping> <url-pattern>/MyServlet</url-pattern> </servlet-mapping> <!-- look for "servlet-name" tutorial in Google! -->

CGPackaging.xml <!--********************WEB class*******************--> <target name="WEB" description="Lecon3.war"> <jar destfile="lib/Lecon3.war"> <zipfileset dir="WebContent/WEB-INF" prefix="WEB-INF"> <include name="*.xml"/> <include name="*.wsdd"/> </zipfileset> <zipfileset dir="WebContent/WEB-INF/lib" prefix="WEB-INF/lib" includes="**/*.jar"/> <zipfileset dir="bin" prefix="WEB-INF/classes"> <include name="applicationWeb/Login*.class"/> <include name="applicationWeb/Manage*.class"/> <zipfileset dir="lib" prefix="WEB-INF/lib"> <include name="Lecon3-CL.jar"/> <zipfileset dir="WebContent" prefix=""> <include name="appliWeb/Manager.jsp"/> <include name="applicationWeb/Login.html"/> <include name="applicationWeb/Manage.html"/> </jar> </target>

Session de client (Paragraphe 7.8.5) Chaque client a une zone pour ses variables Lié à la session par les cookies La servlette retrouve les variables de l’appelant automatiquement

Objets de session dans des servlettes Client 2 Client 21 Serveur Client 1 (cookie) Servlet y = session.getAttribute("xx"); Java bean “xx” Client 2 (cookie) Java bean “xx”

Trouver les Java beans dans la session public public void doGet ( HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(); MyObject myObject = new MyObject (); session.setAttribute("myObject", myObject); x = session.getAttribute("myObject"); . . .

JSP: Java Server Page (Section 7.8) JSP (exécuté sur le serveur) ≠ Javascript (exécuté dans le browser) http://java.sun.com/products/jsp/docs.html voir Servlets and JavaServer Pages: A Tutorial

Comparaison servlettes - JSPs public class Test extends HttpServlet { public void doGet (request, response) { out.println ("<html><body>"); out.println ("<h1>"); out.println ( x.toString() ); out.println ("</h1></body>"); } } Servlette <html><body> <h1> <%= x.toString() %> </h1></body JSP

Création d’une JSP JSP ( code ) ( + ) ( html ) Servlet Java source JSP compilateur Java compilateur Exécution JSP ( code ) ( + ) ( html ) Servlet Java source Servlet Java code html html serveur browser http://www.ch/xxxx.jsp Réseau

Exemple d’une page JSP (Vue globale) <html> <head><title>File</title></head> <body> <h1>Example</h1> <%! declarations %> <% code Java %> Nouvelle valeur de l'attribut: <%= attribute %> <p> <form action="http://localhost:8080/Exercice3-WEB/File.jsp"> <input type="text" name="attribute"/> <input type="submit"/> </form> </body> </html>

Page JSP: déclaration <%! declarations %> <!-- déclaration d’attributs Attention, le même objet servlette est partagé par tous les clients -->

Page JSP: affichage Affichage d’une valeur de variable: Affichage du retour d’une méthode: <%= myClass.text() %> <% // Java code out.println( "Text <p>" ); %>

Conditional statements <% if (error!=null) { %> <b>Error: <%=error.message()%><b> <% } %>

Conditional statements (code généré) if (error!=null) { out.print(“<b>Error:”); out.print(error.message(); }

URL d’une JSP http://localhost:8080/Exercice3/File.jsp

Autres instructions JSP <%@ pageimport="packName.*" %> request, response et session sont définis par défaut dans une JSP

Standard Tags JSP jsp:include jsp:useBean jsp:setProperty jsp:getProperty jsp:forward jsp:plugin http://java.sun.com/products/jsp/docs.html Voir 2.0 PDF ou HTML et Servlets and JavaServer Pages: A Tutorial

Applet <jsp:plugin type="applet" code="package.HorlogeApplet" width="370" height="50"> </jsp:plugin>

Session / Java bean <jsp:useBean id = "myForm" scope = "session" class = "app.InputForm" /> <jsp:setProperty name = "myForm" property = "attribute" value ="<%= x %>" /> class InputForm { int attribute; // getter/setter créés au moyen d’Eclipse }

Utiliser un tag non standard Définition: <%@ taglib uri = "pack/myTag.tld" prefix = "tag"%> Utilisation: <tag:myTag/>

Classe tag Correspondante package pack; import java.io.IOException; /** * @jsp.tag * name = "myTag" * description = "A test class for tags" */ public class myTag extends TagSupport { public int doStartTag() { JspWriter out = pageContext.getOut(); out.println("I am a tag"); return 33; } } Classe tag Correspondante

Description d’un tag: MyTag.tld Créé par les xDoclets ?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name>xdoclet-build</short-name> <tag> <name>myTag</name> <tag-class>pack.myTag</tag-class> <description><![CDATA[A test class for tags]]></description> </tag> </taglib>

Où se retrouve le fichier JSP compilé en Java? C:\jboss-4.0.0\server\default\work… (n’est compilé que lorsqu’on l’appelle)

Java bean package p; public class Result implements Serializable { public Result() { } // optionnel int xxx; public int getXxx() { return xxx; } public void setXxx(int xxx) { this.xxx = xxx; Dans Eclipse: sélectionner int xxx clic-droit sur la sélection Source > Generate Getter…

Utilisation d’une session et d’un Java bean sendRedirect Page HTML Servlet Page JSP Servlet Session client (cookies) Java bean Java bean Java bean

Architecture de l’exercice 1 Java Bean Résultat Page.jsp Affichage résultat Nouvelle entrée Servlette.java Calcul

Architecture de l’exercice 2 Même Page.jsp Page.jsp Calcul + Affichage résultat Nouvelle entrée Page.jsp Calcul + Affichage résultat Nouvelle entrée Java bean Résultat

Database access with the help of persistent objects EJB: Enterprise Java Beans

Web Application (J2EE) DB Server Client Network Container Container JBoss Server Container Container Session EJB Entity EJB DB Client Tomcat Browser Servlet proxies Container Entity EJB x.html Network

Client-server Application (J2EE) JBoss Container Container Client Session EJB Entity EJB Client proxies DB Container Network Entity EJB

CMP entity beans (Container Managed Persistency) BMP, Bean Managed Persistency will not be studied as there are better alternatives

Specification of CMP entity beans in WebLang CMP bean: relations methods attributes finders / creators

Definition of an object in WebLang cmpbean Town { package geo; String name; // DB attributes int numero; public void myMet (String s) { System.out.println(s); } // creators - finders

CMP Bean: method create cmpbean Person { package beans; String firstName; String lastName; // attributes = DB columns int age; public Person createPerson ( String firstName, String lastName ); // age not initialised } // the arguments of the create must correspond // to the attributes. They are stored in the latter.

Creation and use of an object in WebLang Town t ; Country c ; t = townHome.create("Lausanne"); c = countryHome.create("Switzerland"); System.out.println( t.getName() ); c.setName( "Suisse" );

CMP Bean: finder method Town findByName (String s) { query = "SELECT OBJECT(o) FROM Town o WHERE o.name=?1" } // more details later

Find an object in WebLang Town t ; try { t = townHome.findByName("Lausanne"); } catch (javax.ejb.FinderException fe) { t = townHome.create("Lausanne"); } System.out.println( t.getNumber() );

Servlet using a bean servlet myservlet { package servlets; public void newPerson ( PrintWriter out, String firstName, String lastName, int age) throws Exception { Person aPers; aPers = personHome.createPerson (firstName, lastName); aPers.setAge(age); } // it is a simple means to test CMP beans, an html // file that calls this servlet is created automatically

Java Client (remote) jclient Ouf { package clientPack; public void method1 (String s1, String s2) { Person aPers; Course aCourse; aPers = personHome.createPerson("a", s1); aCourse = courseHome.createCourse("prof", s2); } // WebLang generates automatically a remote access

Reading the HSQLDB database http://localhost:8080/jmx-console Select: service=Hypersonic (fifth line under jboss) Select invoke (below startDatabaseManager) Look at the task bar and let the DB window appear. Click View/Refresh tree in this window Examine the tables (Command > Select …)

Fichiers auxiliaires des CMP entity beans (générés par WebLang et par XDoclet)

Files generated by WebLang and by the xDoclets src/control Game.java GameCMP.java GameLocalHome.java GameLocal.java GameHome.java GameUtil.java sources of the beans interfaces of the proxies

Parts of a CMP entity bean EJBContainer servlet other EJB XxxxLocalHome create findByPrimaryKey Xxxx ejbCreate ejbPostCreate ejbFindByPrimaryKey ejbLoad ejbStore userMethods XxxxEntityBean XxxxLocal userMethods

Instantiation of a persistent object InitialContext lookup 1 XxxxHomeProxy create findByPrimaryKey 2 client servlet bean XxxxObjectProxy userMethods EJB EJB XxxxObjectProxy userMethods EJB XxxxObjectProxy userMethods 3

Lookup to get a home proxy TownLocalHomeProxy townLocalHomeProxy = null; Context context = new InitialContext(); Object ref = context.lookup("store_PersonLocal"); townLocalHomeProxy = (TownLocalHomeProxy) PortableRemoteObject.narrow ( ref, TownLocalHomeProxy.class ); // narrow = cast from object to TownLocalHomeProxy

Class specifying a CMP entity bean package store.ejb; import javax.ejb.EntityBean; import javax.rmi.PortableRemoteObject; /** * @ejb.bean * name = "Customer" * display-name = "CMP Entity Bean" * description = "Description of the CMP Entity Bean" * view-type = "both" * type = "CMP" * primkey-field = "pk" * jndi-name = "store_CustomerRemote"  * local-jndi-name = "store_CustomerLocal" * @ejb.pk * class ="java.lang.Long" */ public abstract class Customer implements EntityBean { EntityContext entityContext; . . .

CMP entity bean (primary key) /** * Attribute Pk is used as primary key by default. * @ejb.persistent-field */ public abstract java.lang.Long getPk(); public abstract void setPk(java.lang.Long pk); * Default remove method * @throws RemoveException * @ejb.remove-method public void ejbRemove() throws RemoveException { }

CMP entity bean: Attributes /** * A pair of getter / setter for each attribute * * @ejb.persistent-field * @ejb.interface-method * view-type = "both" */ public abstract String getAtt() ; public abstract void setAtt(String att) ;

Control files generated by the xDoclets META-INF ejb-jar.xml jboss.xml jbosscmp-jdbc.xml

Extrait de ejb-jar.xml (src/META-INF) <display-name>CMP Entity Bean</display-name> <ejb-name>Patient</ejb-name> <home>predimed.PatientHome</home> <remote>predimed.Patient</remote> <local-home> predimed.PatientLocalHome </local-home>

Fichier.ear  deploy Fichier.ear application.xml // références les fichiers ci-dessous Fichier.jar // contient les EJBs Fichier.war // contient les servlettes, passé à Tomat <module> <ejb>Test.jar</ejb> </module> <module> data/jboss-app/application.xml <web> <web-uri>Test.war</web-uri> <context-root>/Test</context-root> </web>

Session beans (Pattern de façade)

Collections gérées par une session bean Server collection JBoss Entity EJB Client Session EJB Entity EJB Entity EJB Browser Servlet proxies Entity EJB proxies proxies Network Les collections (relations) doivent être gérées dans des session ou CMP beans

Une session bean en WebLang sbean ControllerSession { package beans; state Stateful; // optionnel String st; public ControllerSession create (String st); public void newPerson (String firstName, String lastName, int age) throws Exception { Person aPers; aPers = personHome.createPerson(firstName, lastName, age); } }

Bean Managed Transaction sbean ControllerSession { package beans; (Container managed transaction) transaction Bean; // optionnel, par défaut une CMT est créée state Stateful; // optionnel String st; public ControllerSession create (String st); public void newPerson (String firstName, String lastName, int age) throws Exception { Person aPers; beanContext.getUserTransaction().begin(); // optionnel aPers = personHome.createPerson(firstName, lastName, age); beanContext.getUserTransaction().commit(); // abort() } }

Relations entre CMP beans

1:N Relation Y X N 1 4 23 8 5 WebLang, object view: cmpbean X { relation <hasY 1:N hasX> Y; } 23

1:1 Relation (bidirectionnelle) Y X 23 4 23 WebLang: cmpbean X { relation <hasY 1:1 target hasX> Y; } cmpbean Y { relation <hasX 1:1 hasY> X;

N:M Relation 23 4 27 X 8 Y 24 23 5 5 23 8 27 8 24 4

N:M Relation (toujours bidirectionnelle) WebLang: cmpbean X { relation <possessesY N:M hasX> Y; …attributes… } cmpbean Y { relation <hasX N:M possessesY> X;

xdoclets pour les relations /** * Implementation of the relationship: getCollection * @ejb.interface-method * view-type = "local"  * @ejb.relation * name="Courses-Students-NM" * role-name="Courses-N-role" * target-ejb="Students" * target-role-name="Students-M-role" * target-multiple="yes" * @jboss.relation-mapping * style="relation-table" * @jboss.relation-table * table-name="CoursesXStudents" * @jboss.relation * related-pk-field = "pk" * fk-column="students_pk" * fk-constraints = "false" * @jboss.target-relation * fk-column = "courses_pk" */ public abstract java.util.Collection getStudentsN(); xdoclets pour les relations

Operations concernant les relations entre beans (WebLang)

Relations utilisées dans les pages suivantes cmpbean Country { relation <hasCapital 1:1 isCapitalOf> Town; relation <hasTown 1:N isLocatedIn> Town; } cmpbean Town { relation <isCapitalOf 1:1 hasCapital> Country; relation <isLocatedIn N:1 hasTown> Country;

Utilisation d’une référence bidirectionnelle 1:1 Country-Capital Town t = townHome.create("Bern"); Country c = countryHome.create("Switzerland"); t.setIsLocatedIn(c); System.out.println( t.getIsLocatedIn().getName() ); // setIsLocatedIn est automatiquement définie quand on spécifie la relation isLocatedIn

Addition d’un élément à une relation Country (1) – Town (N) Town v ; Country c ; t = townHome.create("Lausanne"); c = countryHome.create("Switzerland"); t.setIsLocatedIn(c); // 1:1 side t = townHome.create("Bern"); c.addHasTown(t); // 1:N side

Déposer une relation et y accéder Collection collection = aCountry.getHasTown(); Iterator it = collection.iterator(); while (it.hasNext()) { // Java 1.4 System.out.println( ( (Town) it.next() ) .getName() ); }

Déposer une relation et y accéder Collection collection = aCountry.getHasTown(); for (Object o: collection) { // Java 1.6 System.out.println( ( (Town) o ) .getName() ); }

addHasTown est introduit par WebLang void addHasTown(t) { getHasTown().add(t); } // standard add et remove de Collections // ajouté automatiquement par WebLang removeHasTown(t) { getHasTown().remove(t); Les collections doivent être manipulées à l’intérieur de transactions

Résumé des relations et de leurs méthodes indication in Xxxx Other end in Yyyy methods available <elemY 1:1 elemX> Yyyy no relation <elemX 1:1 target elemY> Xxxx <collX 1:N elemY> Xxxx Yyyy y = getElemX() setElemX(yyyy) <elemY 1:1 target elX> Yyyy no relation <elX 1:1 elemY> Xxxx Yyyy y = getElemY() setElemY(yyyy) <collY 1:N elemY> Yyyy no relation <elemX N:1 collY> Xxxx Collection y = getCollY() setCollY(collection) addCollY(yyyy), removeCollY(yyyy) <collY N:M collX> Yyyy no relation <collX N:M collY> Xxxx

Comparaisons entre objets CB h1 = cBHome.create("5"); CB h2 = cBHome.findH("5"); if (h1 == h2) ; // pas valable ! if (h1.getPrimaryKey().equals(h2.getPrimaryKey()) System.out.println("2 x the same bean"); if ( ((Long)h1.getPrimaryKey()).intValue() == ((Long)h2.getPrimaryKey()).intValue()) System.out.println("2 x the same bean");

(voir exemple du paragraphe 11.2.6.8) Finders http://ltiwww.epfl.ch/~petitpie/ProgrammationInternet/ejb-2_1-fr-spec.pdf (voir exemple du paragraphe 11.2.6.8)

Finder retournant un objet ( WebLang ) Course findCourse (java.lang.String name) { query = "SELECT OBJECT(o) FROM Course o WHERE o.courseName=?1" }

Source d’un finder /** * Pays CMP Entity Bean * * @ejb.bean * name = "Pays" * display-name = "CMP Entity Bean" * description = "Description of the CMP Entity Bean" * view-type = "both" * type = "CMP" * primkey-field = "pk" * jndi-name = "geo_PaysRemote" * local-jndi-name = "geo_PaysLocal" * @ejb.pk * class ="java.lang.Long" * @ejb.finder * signature = "java.util.Collection findByVilleAvecM (java.lang.String s)" * query = "SELECT OBJECT (p) FROM Pays p, IN (p.contient) v WHERE v.nom LIKE CONCAT(?1, '%')" * @generated */ public abstract class PaysBean implements EntityBean { Source d’un finder

Build/classes/META-INF/ejb-jar.xml <query> <query-method> . . . <query> <query-method> <method-name>findVille</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql><![CDATA[SELECT OBJECT(v) FROM Ville v WHERE v.nom=?1]]> </ejb-ql> </query>

Tester si un objet existe en WebLang Country c = null; try { c = countryHome.findByName("Switzerland"); } catch (javax.ejb.FinderException fe) { c = countryHome.create("Switzerland"); }

Finder retournant une collection (ici la table entière) java.util.Collection findCourses () { query = "SELECT OBJECT(o) FROM Course o" } Note: les collections retournées par les finders peuvent être manipulées dans servlets.

Références cascadées 1:1 Option findOptionByProf (java.lang.String profName) { query = "SELECT OBJECT(s) FROM Option o WHERE o.course.profName=?1" } // le finder doit être inclus dans le CMP bean // qui définit l’objet retourné

Relation 1:1 retournant une collection de membres appartenant à la relation public java.util.Collection findCountryByCapital (java.lang.String capital) { query = "SELECT c.capital FROM Country c WHERE c.capital.name LIKE CONCAT('_', CONCAT(?1, '%‘)) " } // On utilise une collection, parce qu’on suppose que // plusieurs beans peuvent correspondre au même critère

Relation 1:N Country <contains 1:N isIn> Town public java.util.Collection findCountryByTownName (java.lang.String name) { query = Country "SELECT OBJECT(c) FROM Country c, IN (c.contains) t WHERE t.name=?1" }

Relations 1:N cascadées Country : contains Town : hasNb Number public java.util.Collection findCountryByNumber (int number, java.lang.String name) {  query = "SELECT OBJECT(n) FROM Country c, IN (c.contains) t, IN (t.hasNb) n WHERE c.name = CONCAT("%", ?2) AND n.value < ?1" }

Relations cascadées A 1:1 B 1:1 C 1:1 D - dd public A findAByX (java.lang.String name) { query = "SELECT OBJECT (o) FROM A o WHERE o.b.c.d.dd=?1"  }

Relations cascadées An 1:N Bn 1:N Cn 1:N Dn - dd public java.util.Collection findA(java.lang.String name) { query = "SELECT OBJECT (o) FROM An o, IN(o.bnN) bx, IN(bx.cnN) cx, IN(cx.dnN) dx WHERE dx.dd=?1" }

Relations en cascade (la query retourne un An) An  1:1  Bn   1:N   Cn   1:1 Dn  -  dd public java.util.Collection findAn (java.lang.String name) { query = "SELECT OBJECT (o) FROM An o, IN(o.bn.cnN) cx WHERE cx.dn.dd=?1" } // à introduire dans un bean An

(la query retourne un Bn) Relations en cascade (la query retourne un Bn) An  1:1  Bn   1:N   Cn   1:1 Dn  -  dd public java.util.Collection findBn (java.lang.String s) { query = "SELECT o.bn FROM An o, IN(o.bn.cnN) cx WHERE o.aa=?1" } // à introduire dans un bean Bn car il retourne une // collection de Bn

Transactions

Transactions dans les session beans transaction Bean; La transaction n’est pas gérée automatiquement, le développeur doit insérer le code qui la gère.

Relation N:M manipulée depuis une session bean Cours Etudiants N M Expérience: Enregistrer un étudiant dans un cours Voir si l’étudiant est visible depuis le cours

beanContext.getUserTransaction().begin(); s1.addCourse(c1); // s1, s2 are students and s1.addCourse(c2); // c1,c2 courses s1.addCourse(c3); s2.addCourse(c3); System.out.println("Additions terminées"); Thread.sleep(10000); // suspendue pendant 10 sec pour voir // dans la base de données for (Students s : c3.getStudentsN()) { System.out.println("c3.collection"+s.getName()); } beanContext.getUserTransaction().commit();

Transactions CMP Bean A Transaction présente avant d’entrer B CMP Bean B Transaction crée par le conteneur pour B

Dans le CMP bean (WebLang) transaction RequiresNew; Dans la méthode du CMP bean beanContext.setRollbackOnly();

Transaction avant l’exécution Types de transaction Type de transaction Transaction avant l’exécution Réaction du conteneur Required présente aucune est gardée une nouvelle RequiresNew Mandatory erreur

Appels locaux/distants Les programmes situés sur des ordinateurs autres que le serveur peuvent accéder à une session beans ou une CMP entity beans de la même manière que les servlets ( mais par le biais de XxxRemoteHomeProxy ) Il ne peuvent pas manipuler les relations des CMP beans (pour plusieurs raisons)

Classes / jclients de WebLang WebLang gèrent les home interfaces, les entités CMP et les noms des classes des session beans de même que les input/output channels dans la plupart des modules En particulier dans les jclients et dans les classes. Note: les classes doivent contenir l’indication access Remote; si elles ne sont pas dans le serveur.

class or jclient Module jclient Ouf { package clientPack; inputchannel varName (topic, "TopicName") { … } void method1 (String s) { Person aPers; Course aCourse; aPers = personHome.createPerson(s+"pers"); // CMP bean aCourse = courseHome.createCourse(s+"course"); } void method2 () { List aList; String str = "Text = "+listHome.create().text(); // session bean System.out.println(str); } }

Struts

Basic structure of struts PersonManagement SportManagement Servlet Servlet Servlet Servlet JSP JSP sport person sportName location personName sportForm The forms are saved in the HTTP session Under the name derived from the class ! personForm

Output of data (same for input) sportForm location Struts sportForm.setLocation("xxx") JSP <bean:write name="sportForm" property="location"/> <html:text name="location"/> No direct connection !

Basic structure of struts PersonManagement SportManagement Servlet Servlet Servlet Servlet JSP JSP sport person 2 1 3 personName sportName location personForm sportForm The forms are saved in the client session Under the name derived from the class !

1 Librairies Struts: Action Form ( = java bean ) /** * @struts.form name="personForm" */ public final class PersonForm extends ActionForm { private String name; public String getName() { return (this.name); } public void setName(String name) { this.name = name; } // ActionForm has code to fill in the form from the URL

2 Librairie JSP pour Struts: HTML Form JSP: input.jsp <h3>personForm.sportForm</h3> <html:form action="/personManagement"> sportName <html:text property="name"/> <html:submit/> </html:form> // Plusieurs paramètres de l’action sont définis dans struts-config.xml // en particulier une form est attribuée à cette action et name est le nom d’un // champ de cette form

3 Struts: Action Servlet public final class PersonManagement extends Action { PersonForm f; public ActionForward execute (ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { try { f = (PersonForm) form; f.getName(); return (mapping.findForward("sport")); } catch(Exception e) { // trap exceptions that may occur in your servlet e.printStackTrace(); // you will get better error messages ! return (mapping.findForward("error")); } } } // L’action form passèe comme argument est automatiquement // remplie à partir des arguments de l’URL 3 Struts: Action Servlet

Fichier auxiliaire: struts-config.xml (généré par xDoclet) <action-mappings> <action path="/personManagement" type="management.PersonManagement"  // servlet class name="personForm" // name in HTTP session scope="session" input="/pages/Error.jsp" unknown="false" validate="true" > <forward name="sport" // name that can be used as next page path="/pages/sport.jsp" redirect="false" /> </action>

Action Forms  CMP Beans Main personForm[] Action forms Course Person[] PersonForm finder ou getCollection Person Recrée une collection et copie ses éléments dans l’autre collection CMP beans // code prochaine page

Action Forms  CMP Beans Course Person[] per Main personForm[] per PersonForm PersonForm Person Person Pseudo-code course.setPer( new ArrayList() ) for (each main.per[]) { x = personHome.create(per[].attributes) course.addPer(x) }

- Action forms, - arrays of action forms, - trees of action forms

Java beans composés person In/out Action Action In/out Input sport job SportManagement In/out PersonManagement Action Action In/out Input sport job jobName location personName jobName location sportName location jobName location personName jobName location jobName location sportForm[ ] jobName location jobName location Pas supporté jobName location personForm jobForm[] sportName location jobForm[ ] sportForm // Toutes les Action Form envoyées à // une action doivent avoir le même type

Tree of action forms /** * @struts.form name="personForm" */ public final class PersonForm extends ActionForm { . . . private SportForm sportForm; // sub-form public SportForm getSportForm () { return (this.sportForm); } public void setSportForm (SportForm sportForm) { this.sportForm = sportForm;

Array of sub-action forms ( x[ ] or Collection or Set ) /** * @struts.form name="personForm" */ public final class PersonForm extends ActionForm { . . . private Collection sportForms; public Collection getSportForms () { return (this.sportForms); } public void setSportForms (Collection sportForms) { this.sportForms = sportForms;

Reference to an attribute of an Action Form In the action servlet f.getName(); In the JSP <html:text property="name"/> the form in which name is looked for is linked to the JSP by a definition introduced in struts-config.xml

Reference to an attribute of a Sub-Action Form In the action servlet f.getSportForm().getName(); In the JSP <html:text property="sportForm.name"/> the form is linked to the JSP within struts-config.xml

Reference to an array of Sub-Action Forms In the action servlet (first element ! ) o = ((ArrayList) f.getSportForms(); name = ((SportForm) o.get(0)).getName(); // f is linked to the JSP in struts-config.xml In the JSP <html:text property="sportFormN[0].name"/> // The element passed to the property can be // an ArrayList or an array such as String[]

Tags in the JSP and the Struts <jsp:useBean id="managementForm"  scope="session" class="man.ManagementForm"/> <bean:write name="managementForm" property="warning" filter="false"/> // prints the value of the property on the page http://localhost:8080/struts-documentation http://ltiwww.epfl.ch/WebLang/references.html

HTML form in a JSP <h3>PetForm</h3> <html:form action="/Supplier_State_0_Action" > <html:hidden name="petForm" property="<%= page_prop_token %>" value="<%= pageId %>" /> <table border=0><tr> <tr><td>       name     <td><html:text property="name"/> <tr><td colspan=2 align=center> <html:submit property="submit">submit</html:submit> </table> </html:form>

Array in an HTML form <html:form action="/Supplier_State_0_Action" > <html:hidden name="petForm" property="<%= page_prop_token %>" value="<%= pageId %>" /> <table border="0" cellspacing="1"> <tr><td> <table border="0" width="100%"><td>subName</table> <td> <table border="0" width="100%"><td>number</table> <td> <table border="0" width="100%"><td>check</table> <tr><td> <table border="0" cellspacing="1"></table> <!-- tableau  transparent suivant <tr><td colspan=10 align=center> <html:submit property="submit">submit</html:submit> </table> </html:form>

Iteration on the array (or collection) <logic:iterate name="petForm" property="thingN" id="item1" indexId="index1"> <tr><td> <table border="0" width="100%"<%=color[index1.intValue()%2]%>> <td>  <bean:write name="item1" property="subName"/> </table> <td> <td><bean:write name="item1" property="number"/> <table border="0" width="100%" <%=color[index1.intValue()%2]%>> <td><html:checkbox property='<%="thingN["+index1.intValue()+"].check"%>'/> </logic:iterate> cette valeur est retournée dans l’URL

Internationalization (a.k.a. i18n) Properties defined in resources/application.properties resources/application_fr.properties Introduced in the JSPs by <bean:message key=“struts.page.form.text"/> (see the file for details) If the browser is set to French application_fr.properties is used

Translation of the properties Copy resources/application.properties to resources/application_fr.properties and edit the content of the new file

Struts in WebLang Architecture pour: Machine à états finie Gestion des pages

Assurer une confirmation! L’utilisateur clique le bouton Confirm L’ordre est exécuté par le serveur L’utilisateur clique le bouton BACK du browser Il reclique Confirm  erreur: double entrée Comment le serveur évite-t-il le doublon ?

Eviter le doublon Chaque page contient un hidden field avec un numéro unique Avant de lire les paramètres de la page, on vérifie que le numéro est celui de la dernière page envoyée Cela implique un code homogène

State Machine Login Register Fill a cart Confirm the cart Show the bill Confirm the order (only once)

WebLang use of the JSPs and servlets personName sportName location state == 1 transition from state 1 state = 2 state == 2 transition from state 2 state = 1 JSP JSP State_1 State_2

WebLang use of the JSPs and servlets sportName location FSM bean FSM bean JSP JSP Where to start ? In the bean! Same bean, but different states personName

Finite State Machine in a Struts page_0 not confir- med showBasket page_1 1 confirmed 2 page_2 OK

WebLang Module : states and pages struts PersonManagement { package management; stateMachine state State_0 > person; state State_1 > job; . . . FSM . . . page person { personForm; personForm.sportForm[ ]; personForm ("Comment", submitName) ; }

WebLang Module : Finite State Machine state State_0 > supply; state State_1 > supplyConfirmation; switch (sessionState) { case State_S: sessionState = State_0; break; case State_0: Pet pet = petHome.create( petForm.getName() ); sessionState = State_1; case State_1: if (supplyConfirmation.getConfirmation()) } // Pure Java code

WebLang Module : Forms (Java beans) form SportForm { package fmPack; String sportName; int location); } form PersonForm { // sub-form String name ; JobForm jobForm; SportForm sportFormN [ ] ; form JobForm { String jobName; int location;

Different display formats page SomePage { petForm; // displays all the fields petForm.thingN[ ]; petForm.bbb (MySubmit); // displays a MySubmit button petForm.ccc (Cancel); // display a button petForm.aaa (); // displays no button }

Struts JSP struts Supplier { . . . page supply { petForm; petForm.thingN[ ]; } form PetForm { package fp; String name; Thing thingN[]; form Thing { String subName, int number, boolean check;

Selection of the visible fields page SomePage { petForm () { readwrite nom; hidden age; } petForm.thingN[ ]; petForm.bbb (MySubmit); }

Selection of the visible fields page SomePage { petForm () ; petForm2<PetForm> () petForm.thingN[ ]; petForm3<PetForm>.bbb (MySubmit); }

Characteristics of the fields hidden message readonly readwrite radio (aaa,bbb) combo (aaa,bbb) password readonly radio (aaa,bbb) | readwrite | combo (aaa,bbb) | password // last lines: one of each group, e.g. readwrite radio

Struts in WebLang Action Forms CMP bean JSPs Action Servlet Struts browseForm.petForm[ ] (form) Struts Action Forms browser (JSP) not confir- med basket.petFrom[ ] (form) showBasket 1 showBasket (JSP) confirmed order- registered (JSP) 2 PetOrder status = ordered OrderItems* (CMP+CMR) CMP bean OK JSPs Action Servlet

Three tiers (overview) browseForm.petForm[ ] (form) Buying Struts browser (JSP) Administrator Struts PetOrder status = toBeChecked OrderItems* (CMP+CMR) areYouThe- Administrator (JSP) not confir- med basket.petFrom[ ] (form) showBasket login showBasket (JSP) 1 checkOrders (JSP) confirmed OrderForm.petForm[ ] not  accept (form) select 1 order- registered (JSP) 2 confirmed OK PetOrder status = ordered OrderItems* (CMP+CMR) SendSupplierPO MDBean Queue Three tiers (overview) file PetOrder status = awaitInvoice OrderItems* (CMP+CMR) Display Business Layer Database + Dataflow Business Layer Display

Prints in WebLang out print println Struts print JSP 1 In the Struts, WebLang automatically defines a stream named out, which contains methods out.print(“xxx”); and out.println(“yyy”); the text produced is automatically printed on the next JSP

Sub-FSMs display enter application display ignore start timeout enter next previous start timeout enter display 2 ignore display_francs 1 display_euros

Sub-FSM Struts A Struts B State_0 State 0 State_1 State_3 State_S (start) State 0 State_R (redirect) 1st return 1st call subsequent calls State_1 Goto B Continue State_3 Return 2nd return

Page_1 Page_0 Groupe Personnes Introduire personnes/ groupes EntrerGroupe EntrerGroupe EntrerGroupe Lister/former groupes Page_2 EntrerPersonne EntrerPersonne EntrerPersonne Nom groupe Personnes Quitter Quitter nomP NomG v Entrer Quitter

JMS: Java Message Services Channels (queues, topics, durable topics) Message driven beans Architecture

Message Driven Bean queue, topic Server Clients Sender queue/topic MDBean Listener queue topic SynReceiver

Types de canaux Each message is rec-eived by a single client Queues Topics Each client receives all messages Durable Topics Each client receives all messages, even if it is temporarily discon-nected Requires (only in input) subscription name username, passwd

Création de queues et topics Queolques queues et topics sont créés quand le serveur JBoss est démarré: A, B, C, D, testTopic (lire les informations imprimées quand JBoss démarre) La queue ou le topic d’un MDBean est créé à la création du MDBean. On peut créer d’autres queues et topics en modifiant les fichiers qui définissent l’environment de JBoss selon http://ltiwww.epfl.ch/WebLang/JBossQueues.html

Canaux disponibles dans WebLang: MDBeans (1 input / 0-n outputs) Servlets, (0-n outputs) JSPs, Struts CMP beans (0-n outputs) jclient, class (0-n inputs / 0-n outputs)

Listener de queue / topic Client inputchannel ch { } Serveur Object operation1() operation2() queue topic Listener Needs C:\jboss-4.0.0\client\jbossall-client.jar

Envoyer des messante à une queue ou un topic Client outputchannel ch { } Server Object ch.send(message) queue topic proxy

Module client ou classe en WebLang jclient MyClient { // or class package myPackage; inputchannel inputName (topic, "MDBTopic") { String s = ((TextMessage)msg).getText()); varName.publish(msg); } outputchannel varName (topic, "testTopic"); public void method(String s) { . . . }

Listener généré par WebLang public class alarmChListener implements javax.jms.MessageListener { public void onMessage(javax.jms.Message msg) { try { System.out.print ((javax.jms.TextMessage)msg).getText(); } catch (Exception t) { t.printStackTrace(); } } } Text specifié dans l’inputchannel

Lecture synchrone // Lire la queue en mode synchrone // (attente de 5 secondes au plus) tmpQueue = (javax.jms.Queue) queueCtx.lookup("queue/C"); queueObj = queueSession.createReceiver(tmpQueue); for (;;) { Message msg = (Message) queueObj.receive(5000); if (msg == null) System.out.println("Timed out"); else System.out.println(msg.getText()); }

Message driven bean

Module MDBean en WebLang Pas de nom (à la diférence des autres) mdbean MyMDB { package myPackage; inputchannel (queue, "MDBQueue") { String s = ((TextMessage) msg).getText()); varName.send(msg); } outputchannel varName (queue, "B"); // executed when a message arrives

Module servlet en WebLang servlet MyClient { package myPackage; // pas d’inputchannel possible ! outputchannel varName (queue, "A"); public void method(String s) { TextMessage tm = queueSession.createTextMessage(s); varName.send(tm); }

Proxy d’un topic (généré by WebLang, similaire pour les queues) public void newTopicEnv(String name, String passwd) throws Exception { Object tmp = initCtx.lookup("UIL2ConnectionFactory"); TopicConnectionFactory tcf = (TopicConnectionFactory) tmp; topicConn = tcf.createTopicConnection(name, passwd); topicSession = topicConn.createTopicSession( false, javax.jms.TopicSession.AUTO_ACKNOWLEDGE ); topicConn.start(); }

Connexion à un topic (généré by WebLang) tmpTopic = (javax.jms.Topic) initCtx.lookup("topic/testTopic"); fromTopic = topicSession.createSubscriber(tmpTopic); fromTopic.setMessageListener(new fromTopicListener());

Exemples d’architecture

Exemple d’environnement pour un jeu dans lequel un dé tourne parmis les joueurs (une fois qu’ils se sont enregistrés) Server Browser Initialise le jeu game Servlet CMP beans (nom de partie) Java client Java client topic Java client

Java client topic GUI setUsername () getUsername () setPosition () setError () Java client Message Listener onMessage () { } topic GUI Listeners actionPerformed() { } invokeLater Business layer FSM () { }

Classes in WebLang class Business { package ppp; outputchannel ch (topic, “testTopic”); access Remote; public Business(LoterieGUI gui) { this(); this.gui = gui; }

La machine d’état est exécutée sur le thread du GUI et le sur le thread qui gère le topic java.awt.EventQueue.invokeLater( new Runnable() { public void run() { // access to the GUI } } );

Machine à états finie public void transition(String source) { try { switch (state) { case 0: if (source != "username") return; game = gameHome().findByName(gui.getGameName()); . . . state = 1; break; case 1: if (source != "nextmove") return; state = 2; case 2: if (source != "done") return; game.moveTerminated(); } } catch (Exception e) { }

Web Services SOAP Simple Object Access Protocol ou Service Oriented Architecture Protocol HTTP remote call SOA Service oriented architecture WSDL Web Services Description Language UDDI Universal Description Discovery and Integration ( tombe dans l’oubli )

Schéma d’un web service Application (standalone) stub Serveur remote object == Java bean Application (sur serveur) stub

Documentation sur la création des Web Services Help > Help Contents > Documentation

Bottom Up: Java bean  service . . . <wsdl:types> <schema elementFormDefault="qualified" <element name="grow"> <complexType> <sequence> <element name="p" type="impl:Person"/> </sequence> </complexType> </element> WSDL package web; public class Test { public Person grow(Person p){ p.setSize(p.getSize()+1); return p; }

Web Services Description Language (WSDL) <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://web" /" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" <!--WSDL created by Apache Axis version: 1.3 Built on Oct 05, 2005 (05:23:37 EDT)--> <wsdl:types> <schema elementFormDefault="qualified" <element name="grow"> <complexType> <sequence> <element name="p" type="impl:Person"/> </sequence> </complexType> </element> . . . <wsdl:port binding="impl:TestSoapBinding" name="Test"> <wsdlsoap:address location="http:// </wsdl:port> </wsdl:service> </wsdl:definitions>

Creation d’un Web Service L’accès à une application est fait au moyen de servlettes développées dans le projet Axis et qui appellent l’objet désigné par l’utilisateur

Test du service (après avoir compilé la classe) Service Explorer WebContent/wsdl/Xxx.wsdl > right click > Web Services > Test with Web Services Explorer JSP de test classe.java > right click > Web Services > Generate Sample JSPs

Top Down: Java bean  service WSDL file (par exemple sur une page WEB qui décrit le service) On obtient un squelette à compléter

Web service en WebLang (seuls les types simples supportés) webservice Simple { package xxx; public int add (int i, int j) { return i+j; }

From an action form to a CMP bean and vice-versa Transfer of data From an action form to a CMP bean and vice-versa

Action Forms CMP Beans Main resultFormN Action forms Course personN PersonForm finder or getCollection Person Recreates a collection and copies one into the other member by member CMP beans // code next page

Action Forms CMP Beans String courseName = result.getCourseForm().getName(); // reads an action form java.util.Collection<Person> coll = personHome.findPersonInCourse(courseName); java.util.Collection<PersonForm> c = new ArrayList<PersonForm> (); for (Person aPerson: coll) { // scan the collection of CMP beans PersonForm personF = new PersonForm(); personF.setFirstName(aPerson.getFirstName()); personF.setLastName(aPerson.getLastName()); c.add(personF); // creates the collection of action forms } result.setPersonFormN( c );

Checking which submit has been clicked If (submit.equals(“OK”)) { . . . } page supply {           petForm.thingN [ ] (OK, Cancel)           readwrite name;       }   }

Exercise Lottery application implemented with Struts Draw first a diagram with the html forms, the action forms, the state machine and the database WebLang modules CMP bean: Customer name Generated automatically struts: Lottery - register(String) - login() - displayResults() html: lottery Start struts CMP bean: Token number

EJB - Hibernate 3 Hibernate 3 allows the beans to be either attached to or detached from the database The beans can thus be used as action forms too, which avoids the tedious transfers from the beans to the action forms The version we will use is based on the @annotations introduced in Java 1.5 See the page WebLang about Hibernate Quelques commentaires ont été ajoutés sous les transparents dans les pages suivantes

Annotations (replace xDoclets) /** * @struts.form name="jeton" */ @Entity public class Jeton implements java.io.Serializable { . . . @Id(generate = GeneratorType.AUTO) public long getId() { return id; } @ManyToOne public loterie.Client getClient() { return (client); Note: En WebLang, tous les ejb3 doivent se trouver dans le même package ------------------------------------------------------------------------- Ces annotations sont générées automatiquement par WebLang

WebLang module (same as cmpbean, but no finders, no creators: they are made in the user’s space) ejb3 MyCountry { package myPackage; relations (Town=1:N); String name; int number; public Country(String name) throws Exception { this.name = name; } public String toString() { String str = "Country id=" + getId() + " name=" + getName(); java.util.Collection<Town> tlist = getTownN(); for (Town town: tlist) { str = str + "\n Town=" + town; return (str);

Configuration parameters config { deploypath = "C:/jboss-4.0.0/server/standard/deploy/"; hibernate_driver = "org.hsqldb.jdbcDriver"; hibernate_url = "jdbc:hsqldb:hsql://localhost:1701"; // for the JBoss database as prepared here hibernate_username = "sa"; hibernate_password = ""; hibernate_dialect = "org.hibernate.dialect.HSQLDialect"; hibernate_dbauto = "create-drop"; // if present, // recreates the tables at each restart } ---------------------------------------------------------------------------- Les paramètres de configurations sont indiqués ci-dessus pour la configuration standard utilisée dans les salles d’ordinateurs

Use of a Hibernate bean javax.persistence.EntityManager em; javax.persistence.EntityTransaction tx; em = hibernate_utility.Manager.open(); tx = em.getTransaction(); tx.begin(); Country c = new Country("Switzerland"); em.persist(c); c.setNumber(1291); // DB updated at commit tx.commit(); // tx.commit() or tx.rollback(); hibernate_utility.Manager.close(); ---------------------------------------------------------------- Les instructions de stockage dans la base de données doivent être placées dans des transactions, ouvertes par les 5 premières lignes de ce transparent et fermées par les deux dernières. L’instruction em.persist(c) attache l’objet c à la transactions, qui mémorise toutes les modifications et les exécute au plus tard au commit Toutes les modifications peuvent être annulées par l’instruction rollback

Finding objects with Hibernate javax.persistence.Query qt; qt = em.createQuery( "select t from Town t where t.name=?"); qt.setParameter(1, name); try {       town = (Town)qt.getSingleResult(); } catch (javax.persistence.EntityNotFoundException enf) { town = new Town(name);       em.persist(town); } ---------------------------------------------------------------- La recherche d’objets de la base de données est faite au moyen des instructions ci-dessus. Si elle est effectuée dans une transaction (pas montrée ici), l’objet est automatiquement attaché et les modifications qu’il subira seront mémorisées et effectuées au commit. Sinon, l’objet est retourné en tant que simple objet. Dans l’exemple ci-dessus, on vérifie si l’objet existe. Si ce n’est pas le cas, on le crée ce qui demande une transaction.

Finding lists of objects with Hibernate javax.persistence.Query qt; qt = em.createQuery("select t from Town t"); try { townN = (Collection)qt.getResultList(); } catch (Exception e) { // some error } ---------------------------------------------------------------- Pour rechercher une collection, on utilise la méthode indiquée ci-dessus.

Using Hibernate objects (size() not written - lazy evaluation) tx.begin(); . . . proprietaire = qt.getSingleResult(); Collection c = proprietaire.getVoitureN(); // The elements of the . . . // collection are retrieved only when needed tx.commit(); for (Voiture v: proprietaire.getVoitureN()) { out.println(v.getName()); // accessed outside the transaction } 09:22:28,774 INFO [STDOUT] org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: package.Proprietaire.voitureN, no session or session was closed ---------------------------------------------------------------- Lorsque l’on recherche un objet qui possède une collection d’autres objets dans une relation, les objets de la relations ne sont recherchés dans la vbase de données que lorsque le programme les appelle (lazy évaluation) pour optimiser les transferts. Donc la transaction doit encore être ouverte à cet instant. Lorsque les objets de la collections sont affichés dans un tableau dans une JSP, la transaction a déjà été fermée, ce qui provoque l’erreur indiquée ci-dessus. À suivre

Using the objects of a Hibernate relationship outside the transaction Owner Car 1 N tx.begin(); . . . owner = qt.getSingleResult(); owner.getCarN().size(); tx.commit(); required to force the computation (other functions may also be used) for (Car c: owner.getCarN()) { otherwise not available out.println(v.getName()); } ---------------------------------------------------------------- Pour assurer que le programme recherche les éléments de la collection, il suffit d’appeler une fonction qui les utilise, par exemple size() comme cela est fait ci-dessus.

Both Action form and Hibernate bean ejb3 MyCountry extends strutsStateMachine.StateForm { package myPackage; relations (Town=1:N); String name; int number; } ---------------------------------------------------------------- Un bean Hibernate peut être également un e ActionForm (les deux sont des Java beans). Pour cela, il suffit d’hériter de StateForm comme ci-dessus. Dans ce cas, il ne faut pas définir la form, elle est automatiquement déclarée par le compilateur WebLang. Les relations d’un ejb3 correspondent aux sous-formes des ActionForm. Cela est valable aussi bien pour les tableaux (1:N, N:M) que pour les objets simples (1:1)

Create and Persist an Action Form // town is assumed to be a form filled in by the user       town.setId(0); // be sure it has not been left // attached by some previous action javax.persistence.EntityManager em; javax.persistence.EntityTransaction tx; em = hibernate_utility.Manager.open(); tx = em.getTransaction(); tx.begin();       em.persist(town); tx.commit(); hibernate_utility.Manager.close(); } ---------------------------------------------------------------- Avant de rendre un objet persistant, il faut être sûr qu’il n’est plus attaché. Cela est fait en mettant son ID à zéro. Il faut éviter qu’il soit dans une transition à ce moment-là, évidemment.

Transactions and display No transaction Transaction Transaction get from the DB display, let the user modify the data store into the DB Must reconnect the bean to a transaction ---------------------------------------------------------------- La situation représentée ci-dessus est fondamentale dans les applications Web. Les deux transactions en vert sont effectuées sur deux appels d’un utilisateur, par exemple dans deux transitions d’un automate construit dans un Struts. Dans la première, on lit des données de la base de données, puis après avoir fermé la transaction, on passe l’objet ou les objets (par exemple le Java bean en jaune) à la couche de présentation (JSP, GUI…) pour que l’utilisateur puisse le modifier. Losque le système doit entrer les modifications dans la base de données, il faut réintroduire l’objet dans un nouvelle transaction (si on gardait la première, le système se bloquerait rapidement). Pour cela, il faut utiliser les instructions présentées sur le prochain transparent. Java bean (ActionForm/EJB)

Reconnect an EJB3 to the DB tx.begin(); // a first call to a servlet em.persist(x); tx.commit(); …Displaying… tx.begin(); // a subsequent call y = em.merge(x); // copy x to a new y y.setName(“new value”); // and persists y tx.commit(); ---------------------------------------------------------------- Le merge détermine s’il y a déjà un objet avec le même ID dans la transaction. Si c’est le cas, il copie les données du nouvel objet dans l’objet attaché et il retourne l’objet de la transaction. Si ce n’est paas le cas, il crée un nouvel objet dans la transaction, copie les données du nouvel objet dans l’objet nouvellement créé et retourne ce dernier (ce qui n’est pas très rusé, mais il semble que ce soit bien le cas).

Handling a relationship Owner Car tx.begin(); em.persist(owner); for (Car c: cars) { em.persist(c) owner.add(c); c.setCar(owner); // indispensable to introduce it into the DB } // because the reference is defined in table car tx.commit(); 1 N ---------------------------------------------------------------- Les connections des relations ne sont pas effectuées automatiquement dans les deux sens, il faut le faire explicitement. La base de données n’est correctement mise à jour que si l’objet qui correspond à la table de la base de données est connecté à la relation: setXxxx(yy) pour une relation xxxx -> yy (1:1) setXxxx(yy) pour une relation yy -> xxxx (1:1 target ou 1:N)

Merging a relationship (could be done by using cascade) Owner Car 1 N tx.begin(); x = em.merge(owner); for (Car c: owner.getCarN()) { x.add(em.merge(c)); // reintroduce the merged } // objects into the new object owner = x; // optional: remettre l’objet dans son pointeur request.getSession().setAttribute(“owner”, owner); // et tx.commit(); // dans la servlet-session x : Owner c : Car 1 N ---------------------------------------------------------------- Quand un objet est “mergé”, les collections de ses relations ne sont pas automatiquement “mergées”. Pour cela il faudrait utiliser l’annotation cascade qui n’est pas encore disponible en WebLang. Pour une relation simple (1:1), il suffit de “merger” l’objet référencé. Pour une relation N:M ou 1:N, il faut “merger” chaque objet et pour cela les copier dans la collection du nouvel objet comme indiqué ci-dessus. Note: La première version de ce transparent utilisait un moyen un peu plus compliqué (et avec une erreur!)

SQL beans SQL beans have been devised at the EPFL: they present the same structure as Hibernate 3 (particularly within WebLang), but they only use JDBC and the standard SQL Much simpler to debug, as all statements may be traced within the debugger No home, the object must be created to hold the finder (instantiation by new)

SQL Bean Example sqlbean Town extends strutsStateMachine.StateForm { package appliT; relations ( Country = N:1, <isCapitalOf 1:1 hasCapital> Country); String name; public long findPK_OfTown() throws Exception { query = "SELECT * FROM Town WHERE name=$name;" } } TownN { public void findN_TownList(String s) throws Exception { query = "SELECT * FROM Town WHERE name>$s" }

Use of an SQL bean // we assume that country has been created // and filled by the Struts mechanism case State_1: long pkC = country.findPK_OfCountry(); if (pkC!=0) { country.reloadAll(pkC); } else { country.store(); } country.addTownN(town); // town.setCountry(country); // either this line or the line // above; the second one is // called automatically

Finders TownN tn = new TownN(); try { tn.findTownList(“N”); } catch (weblangUtils.SQLException we) { System.out.println(“Not found”); } for (Town t: tn) { System.out.println(“t.getName()); } …………………………………………………………….. TownN { String name; public void findTownList (String s) throws Exception { query = "SELECT * FROM Town WHERE name>$s" } } Finders

FSM of the SQL beans o = new Xxx() Detached object o.set(o1) o.add(o1) o.store() o.set(null) o.remove(o1) pk=o.findPKXx() o.findXx() o.reload(pk) o.store() o.delete() Attached object pk!=0 o.delete() Linked object pk==0 o.reload(0) o.delete() o.set(null) o.remove(o1) o.set(o1) o.add(o1) o.reloadAll() o.storeAll() Attached + linked + connected object pk!=0 rel!=0 o.deleteAll() o.reload() o.reloadAll() o.update() o.updateAll()

States of the SQL objects Detached: The object has been instantiated Attached: The object has a corresponding set of data in the database Linked: The object is embedded in a structure, but it has no primary key Attached, linked The object is available in the database, and connected: as well as in memory, within some relationship

Operations of the SQL beans store Copies the data of the object into the database, new primary key inserted in the object findXxx Query method returning a DB row, the object must be instantiated before the method is called findPKXxx Returns the value of the primary key (or 0), method may also throw an exception reload(pk) Method copies the data of the object into a DB row with primary key pk update Dual of the reload, updates the database row that has the PK found in memory

More Operations delete Removes the data in the database, not the memory, resets the object’s primary key set, add Establishes connections between remove the objects, the two directions of the relationship are handled storeAll Call all the objects bound by deleteAll a relationship (not recursively) reloadAll updateAll

RMI Application interface interface Xxxx Xxxx Client Server Xxxx Xxxx RemoteXxxx Xxxx (stub) Xxxx (skeleton)

RMI: inverse communication (by transmitting the stub) Server rmiregistry Transfer (skeleton) Client 1 Transfer (stub) 2 myRemStub MyRemote (skeleton) MyRemote (stub) 3

RMI Module rmi Test { package rmis; public void print (String s) { System.out.println("X "+s); } } jclient Client { package rmis; Test x; // as Test corresponds to an rmi interface, // x is automatically initialized RemoteTest y; // y is not automatically initialized, the client // must call new RemoteConnection(true) public void print (String s) { try { x.print(s); } catch (Exception e) { e.printStackTrace(); } } }

Software Engineering

Application / implementation Craig: (http://www.codegeneration.net/tiki-read_article.php?articleId=27) Specifying software means components, interfaces, archit-ectures, or what is sometimes referred to as the "How". Specifying applications means features, capabilities, options, or what is sometimes referred to as the "What". So, it seems odd to me (i.e., Craig ) to use UML (a "how" language) as a universal specification language.

My View Actually, you want to describe the software, the how. The customer can often not read any schema and will require a fast prototype, which is indeed the software. Library (Librarian, book shelves, quiet room) Soft Library (simulator) (terminals, server, software) Each time a book is borrowed in the real library, the librarian borrows a book here = Borrow a book Look for a user A book has been lost Check differences Sort books Reserve a book Software application (terminals, server, software)

Three tiers (overview) browseForm.petForm[ ] (form) Buying Struts browser (JSP) Administrator Struts PetOrder status = toBeChecked OrderItems* (CMP+CMR) areYouThe- Administrator (JSP) not confir- med basket.petFrom[ ] (form) showBasket login showBasket (JSP) 1 checkOrders (JSP) confirmed OrderForm.petForm[ ] not  accept (form) select 1 order- registered (JSP) 2 confirmed OK PetOrder status = ordered OrderItems* (CMP+CMR) SendSupplierPO MDBean Queue Three tiers (overview) file PetOrder status = awaitInvoice OrderItems* (CMP+CMR) Display Business Layer Database + Dataflow Business Layer Display

Exercise of Software Engineering (8) Creation of a stock exchange application. Customers are connected to the bank. The bank keeps a portfolio for each client, transmits the customer orders to the stock exchange. The stock exchange keeps an “order book” that contains the stocks that customers want to buy or sell, with the prices (or price range) they are willing to pay or get. Create a diagram that specifies a customer, a bank and a stock exchange, with CMP beans, queues, session beans… Create a diagram of the software system that will run the application, not of the application itself.

Exercice: Compléter la loterie pour que le client voie une annonce quand le manager a sélectionné les jetons Créer les fonctions qui permettent d’entrer des jetons depuis le client Java (rich client)

Loterie Client Serveur html généré Java bean: LotteryData - constantes générales - client html: display_Manager - tireJetons(int) servlet: Manager - tireJetons(int) - afficheJetons() cmpbean: Client String nom 1 N html: display_GestionJeton - remplitJeton(int) - afficheResultats() servlet: GestionJeton - remplitJeton(int) - afficheResultats() sbean: AccesJetons - addJeton(Client, Jeton) - listeResultats(Client) cmpbean: Jeton int numero attente int etat gagnant perdant html: display_Enregistrement - enregistre(String) - login(String) servlet: Enregistrement - enregistre(String) - login(String) html généré

Loterie Browser Serveur Client Java bean: LotteryData - constantes générales - client html: display_Manager - tireJetons(int) servlet: Manager - tireJetons(int) - afficheJetons() Client topic: testTopic cmpbean: Client String nom listener: class: LoterieGUI (created with Visual Editor) 1 N cmpbean: Jeton int numero attente int etat gagnant perdant

Loterie Browser Serveur Client Java bean: LotteryData - constantes générales - client html: display_Manager - tireJetons(int) servlet: Manager - tireJetons(int) - afficheJetons() Client topic: testTopic cmpbean: Client String nom class: LoterieGUI - display: TextArea - login: TextField - tireJeton: TextField display(String) listener: 1 N cmpbean: Jeton int numero attente int etat gagnant perdant sbean: ClientBean - login(String) - tireJeton(int) invokeLater class: Business - login(String) - tireJeton(int)