Java Enterprise Edition

Slides:



Advertisements
Présentations similaires
Serveur d’applications JEE
Advertisements

ASP.NET v2 + Ajax = Atlas Pierre Lagarde DevDays 2006 Equipé aujourdhui, prêt pour demain !
DOM Document Object Model. Généralités Standard du W3C Parseur XML – Génération dun arbre dobjet – Construction totale de larbre DOM est spécifié en IDL.
Architecture. Architecture Enjeux Les Enjeux Trouver une solution e-Business Accessible à partir d’un navigateur Web Accédant au système via un Portail.
Servlet JSP & © Philippe Poulard.
Exposé de Système - Informatique et Réseau
Programmation Web Les JSP.
Cours 6 : XML et les architectures N-tiers – Tier Applicatif
51 Les technologies XML Cours 7 : Utilisations dXML Janvier Version 1.0 -
Toolkit Web Framework Java pour les IHMs Cédric Dumas mars 2008 contrat Creative Commons Paternité-Pas d'Utilisation Commerciale- Partage.
JORAM Java Open Reliable Asynchronous Messaging

Design Pattern MVC En PHP5.
UV JSP JSP : Java Server Page
UV Servlets Les Servlets
JSP Java Server Pages. Introduction Afin dimplémenter les règles métiers, coté serveur dans une application Web, larchitecture Java propose trois solutions.
Servlet JAVA.
Message-Driven Beans Michel Buffa UNSA modifié par Richard Grin (version 1.0, 21/11/11)
JDBC: manipuler une base de données en Java IFT6800 – E 2007 Jian-Yun Nie.
Projet sur Framework Spring
JSP 2 Crash Course Michel Buffa UNSA
Live Meeting Technique N°3 Thomas LEBRUN – MVP WPF/Silverlight Florent SANTIN – MVP Team System Julien CORIOLAND - MSP.
Présentation des frameworks pour Java EE
Connexion base de données
Injection de dépendances
Introduction aux services WEB
LOG 02 Bases de Données Avancées Rappels sur JSP / Servlet
OPTIMALJ, CONCEPTION ET DÉVELOPPEMENT RAPIDE MDA-PATTERNS-UML EJB 2
Université de Versailles-Saint-Quentin
Java Enterprise Edition
CGI, Servlet. Script CGI, Servlet Motivation Exécution dun traitement coté serveur web Traitement de formulaire Génération de pages html à la volée Ex.
A. Roussanaly - Université Nancy2 AXIS Master MIAGE/SID – Université NANCY2.
Struts 1 & 2 Tlohi ibtissam Tabit boutaina Ilias bouras
M2 – MIAGE/SID Servlet M2 – MIAGE/SID
Documents > J2SE APIs > J2EE APIs
SERVLETS PRESENTATION
Développement Web en J2EE (Servlet & JSP)
Langages du Web Sémantique
Architecture Logicielle Les supports d’applications
ADOBE FLEX 4. © Logica All rights reservedNo. 2 Introduction Flex en action Autour de Flex Logica Le programme.
JSTL JSP Standard Tag Library
Servlets.
JSP (Java Server Pages)
Servlets. 2 H. Fauconnier M2-Internet Contenu dynamique Perl/cgi indépendant de la plateforme Extensions du serveur exemple ASP M2-Internet 3 H. Fauconnier.
1 CSI 2532 Lab6 Application Web et DB Février 27, 2012.
Fabienne Boyer Laboratoire LIG (INRIA-UJF-INPG) Projet SARDES, INRIA Rhône-Alpes APACHE/VELOCITY.
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.
Marc Le BihanStruts 1.x1 Marc Le Bihan. Struts 1.x2 Plan I)Développement web par Servlets et JSP. II)Prise en charge de Struts. III)Principe de fonctionnement.
Les servlets Java Les bases de la génération dynamique HTML en Java Sébastien Limet etGérard Rozsavolgyi Licence Professionnelle
Module I-C3 : Applications Web IUT R&T 2e année
Java Enterprise Edition, anciennement J2EE
Chapitre 2 Développement Web avec les technologies JSP/Servlets
UV J2EE Module Java Expert
Enterprise Java Beans 3.0 Cours INF Bases de Données Hiver 2005, groupe 10 Stefan MARTINESCU.
Java Enterprise Edition
Struts.
1 / / 01 / 2003 Laurent GRANIE & Franck LEGENDRE – MIAGE 3ème année - ARCHITECTURE WEB ARCHITECTURE WEB – COURS III
M2 – MIAGE/SID Servlet et session M2 – MIAGE/SID
Les Servlets Présentation Cycle de vie Principe de fonctionnement
Les Java Server Pages Dans ce chapitre, nous allons :
IFT 6800 Atelier en Technologies d’information Chapitre 5 Introduction aux Servelets & JSP.
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.
MVC et applications Web
Auditeur: Léonardo AMODIO Cours: NFE107
Transcription de la présentation:

Java Enterprise Edition Java EE Java Enterprise Edition Ce document a été contient des parties adaptées de support de cours de P.Y. Gibello, T. Dandelot et C. Dumoulin Le contenu de ce site est mis à disposition selon les termes de la Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 3.0 France.

Historique – Architecture - Offre Introduction à JEE Historique – Architecture - Offre

Historique Java http://docs.oracle.com/javase/6/docs/api/ Ce cours comme tous les cours java ne peut être complet Le professeur ne peut pas tout connaitre L’élève doit souvent chercher dans la javadoc, le professeur guide vers les bonnes classes http://docs.oracle.com/javaee/6/api/

Java EE - Objectifs Faciliter le développement de nouvelles applications java à base de composants Intégration avec les systèmes d’information existants Support pour les applications « critiques » de l’entreprise haute disponibilité, tolérance aux pannes, montée en charge, sécurité etc.

Architecture Décompose le système à concevoir en applications, en composants applicatifs, analyse descendante jusqu’aux modules, aux classes gestionnaires, aux fonctions ou méthodes Modules ou Objets gestionnaire, pour l’architecture logicielle Représente les fonctions du système Implémente les fonctions et sous-fonctions des cas d’utilisation Services (ou fonctions) de gestion de données CRUD (Create, Read, Update, Delete) sur les données métier Services de recherche sur les données métier services métiers Transactions / Paiements Calculs Bien distinguer les modules ou classes gestionnaires des entités ou structures de données ou classes métier ou objets métier issues de l’analyse statique (MCD, diagramme de classe, base de données etc.) Les méthodes d’objets métier ne doivent pas utiliser les ressources tels que la base, les fichiers ou le réseau Les objets métier doivent être « transient » : pouvoir passer d’une couche applicative à une autre

Architectures informatiques Architectures pour une solution projet : Architectures logiques applicative, métier Architectures techniques logicielle, système, réseau, matérielle. Une architecture logique n’est pas technique, elle ne donne que des informations non technique : fonctionnelle, métier, logique, etc. utilisable quelque soit les technologies. Une architecture applicative représente des applications, elle répond à des exigences fonctionnelles de modularité Elle peut être présentée à des personnes ayant peu de compétences techniques. Une architecture technique réponds aux exigences techniques : performance, robustesse, volumétrie, compatibilité, etc., et elle dépend des autres architectures Une architecture logicielle est un zoom dans une application : découpage en composants applicatifs, elle répond à des exigences de maintenance et d’évolutivité Montrer le slide des architectures exemples de chaque type

Architecture logique 4 tiers IHM (ou GUI) : client Frontal (ou front-end) : présentation Dorsal (ou back-end) : métier Persistence : base de données T1 T2+T3 T2 Ceci est un exemple d’architecture logique (non technique) pour une solution composée de 4 logiciels sur 4 types de machines différentes T1 : Affichage (une partie de la vue de MVC) T2 : Vue et Contrôleur de MVC, parfois Vue également : exemple serveur web pour navigateur, serveur web pour iphone T3 : Modèle de MVC T4 : Persistance (sauvegarde entre 2 démarrage de l’application) : base de données, fichiers Le T1 pourrais être un navigateur WEB simple ou un client 3270 (écran vert) ou la console d’une application en ligne de commande. Le T1 et le T2 sont parfois fusionnés (client lourd, application mobile) Le T2 et le T3 sont souvent fusionnés Parfois le T2 est réparti dans les T1 et T3 (client web 2.0 ou riche avec le T1 faisant de l’Ajax ou du XSLT, application mobile avec une inner view en HTML, etc.) T3 T4

Mutualiser le code métier T1+T2 T2 Site Web T2 Frontal API T3 Ceci est un exemple d’architecture logique (non technique) pour une solution composée de 4 logiciels sur 4 types de machines différentes T1 : Affichage (une partie de la vue de MVC) T2 : Vue et Contrôleur de MVC, parfois Vue également : exemple serveur web pour navigateur, serveur web pour iphone T3 : Modèle de MVC T4 : Persistance (sauvegarde entre 2 démarrage de l’application) : base de données, fichiers Le T1 pourrais être un navigateur WEB simple ou un client 3270 (écran vert) ou la console d’une application en ligne de commande. Le T1 et le T2 sont parfois fusionnés (client lourd, application mobile) Le T2 et le T3 sont souvent fusionnés Parfois le T2 est réparti dans les T1 et T3 (client web 2.0 ou riche avec le T1 faisant de l’Ajax ou du XSLT, application mobile avec une inner view en HTML, etc.) T4

Java EE – C’est quoi? http://java.sun.com/javaee Spécifications Modèle de programmation Implémentation de référence Standard en évolution depuis 1997 J2EE 1.0 à 1.4 en 2003, etc... Au départ, applications Web n-tiers Présentation (Servlets puis JSP), essentiellement HTTP Logique métier : EJB Données : JDBC Puis infrastructure de support standard pour EAI Facteurs de rationalisation majeurs (JTA, JMS, JCA, Web Services) Evolution de progiciels existants vers Java EE anciennement, J2EE (Java2 Enterprise Edition)

Architecture 4 tiers JEE WEB Container T2 Browser T1 Servlets JSPs HTTP JDBC JMS JTA JCA JAAS JavaMail JNDI … html T4 jdbc DB T1+T2 RMI / IIOP Appel local JVM Applets java/flash T3 SOAP, REST RMI / IIOP EJBs xxxx SOAP ou REST = WebSercices, utilisables sur Internet RMI / IIOP = CORBA, utilisables sur un réseau privé (pb de bande passante et de pare-feu) public static void main(…) { T1+T2 T4 EIS EJB Container Java Application Java EE Application Server

Offre Commerciale Open Source Open Source conteneur web uniquement : Oracle (ex BEA) WebLogic IBM Websphere (n°1) Open Source JBoss (n°1 en nombre de déploiements) Oracle (ex Sun) Glassfish (« Platform edition ») OW2 JOnAS Apache Geronimo (« Community edition » de IBM Websphere) openEjb Open Source conteneur web uniquement : Tomcat Jetty Apache HTTPd n’est pas un serveur d’application, c’est un complément au container web (ou l’inverse) dédié aux données statiques, au cache, à la répartition de charge.

Conteneur Web couche de présentation Servlet - WAR – JSP – taglib

Conteneur Web 1/2 webapp Webapp web.xml html html Servlet html Servlet jsp Servlet Servlet Servlet jpg css Tomcat : $TOMCAT/webapps/ROOT pour le chemin par défaut jar js html

Conteneur Web 2/2 Contient des applications Web dans un répertoire Une application web est une arborescence de fichier mywebapp/WEB-INF/web.xml mywebapp/WEB-INF/classes/*.class mywebapp/WEB-INF/lib/*.jar mywebapp/**/*.* Un fichier « .war » est une archive zip de cette arborescence Tomcat : $TOMCAT/webapps/ROOT pour le chemin par défaut

Application Web Servlets JSP: Java Server Pages Code java exécuté sur le serveur pour retourner une page HTML Génération de contenu Web dynamique JSP: Java Server Pages Mélange de HTML/XML et de code java Librairies d ’extensions (« taglibs ») Pré-compilation en servlet Exercices 1 : manipulation de Tomcat 2 : manipulation de Jboss si le temps 2 : Servlet Hello world 3 : JSP Hello world

Servlet Programme java appelable depuis une URL Classe qui hérite de javax.servlet.http.HttpServlet Cycle de vie de HttpServlet init() : 1er appel service() : chaque appel, redirection vers doGet() ou doPost() destroy() : arrêt du serveur WEB Appel d’une servlet URL GET : http://myserver/mywapp/HelloWorld : doGet() <form method="post" target="…"> : doPost(), Init: connexion à la base, etc. Service: multi-thread, stateless Autres méthodes du protocole HTTP doPut(), doDelete(), Etc. utilisées pour le développement d’API REST

Exemple de servlet import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorld extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.println("<html><body>"); out.println("<h1>hello word !</h1>"); out.println("</body></html>"); } Consulter la javadoc

Ecrire une Servlet Classe qui hérite de la javax.servlet.Servlet Surcharger la méthode d ’initialisation init(), Utiliser la méthode getInitParameter() Surcharger une méthode de gestion d’appel doPost(), doGet(), doPut(), doDelete(), doOptions() Analyser la requête, Classe HttpServletRequest getParameter(), getCookie(), getSession() Utiliser la classe HttpServletResponse pour répondre getWriter(), setContentType(), setCookie() L’élève doit consulter la javadoc pour plus de détails

formulaire et Servlet Champs des formulaires directement dans des variables : <FORM ACTION="testServlet" METHOD="POST"> Votre nom : <INPUT TYPE=TEXT NAME="nom"> Votre âge : <INPUT TYPE=TEXT NAME="age"> <INPUT TYPE=SUBMIT VALUE="Ok"> </FORM> Dans TestServlet.doGet(), l’objet request contient les saisies: request.getParameter("nom") request.getParameter("age") public void doGet( HttpServletRequest request, HttpServletResponse response) ... { … out.println("Bonjour " + request.getParameter("nom"));

Déployer une servlet Recopier l’application web sous $tomcat/webapps une archive .war ou Un répertoire Contenu de l’application web sous-répertoire « WEB-INF/ » web.xml : déclaration et paramètres de servlets /lib/ : pour les .jar, /classes/ pour les .class Nom de fichiers et de réperoires sensibles à la casse

Déclaration de la servlet apache-tomcat-7.0.30/webapps/myapp/WEB-INF/web.xml <web-app> <servlet> <servlet-name>servletHello</servlet-name> <servlet-class>HelloWorld</servlet-class> </servlet> <servlet-mapping> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app> http://localhost:8080/myapp/hello

Autour des Servlets Gestion de la session : HttpServletRequest.getSession() données de contexte à durée de vie courte stockées sur le serveur addAttribute(), getAttribute(), setMaxInactiveInterval() Gestion des cookies : HttpServletRequest.getCookies() données de contexte à durée de vie plus longue stockées sur le poste client setName(), setValue(), setMaxAge() Filtre Transforme des requêtes et/ou des réponses Classe qui implémente javax.servlet .Filter Déclaré dans web.xml comme une Servlet Une session et plusieurs cookies par utilisateur Session pour garder en mémoire des variables d’une page web à une autre (30 minutes en moyenne, stocker le minimum d’information) Cookies pour garder en mémoire des variables d’une visite à une autre, voir http://en.wikipedia.org/wiki/HTTP_cookie Filtres : pour des traitements transverses (authentification, log, compression, transformations) , voir http://www.oracle.com/technetwork/java/filters-137243.html

JSP Java Server Pages Intégration de code serveur dans un fichier HTML mêmes principes que PHP Code java dans des balises <%...%> Les pages JSP ont l’extension « .jsp » L’interpréteur JSP génère une classe de servlet « .java » par JSP des variables accessibles dans des pages (session, application, request, response) avantage vs PHP: Les JSP sont converties en classes java de type servlet et sont compilés lors du 1er accès client PHP interpètre à chaque appel (sauf mise en place d’un cache d’opcode comme « APC »)

Exemple de JSP Directive <%@page import="java.util.*" %> <HTML> <HEAD> <TITLE>Test HelloWorl en JSP</TITLE> </HEAD> <BODY> <% out.println("Hello world !"); out.println("Hello " + request.getParameter("name"); %> <p>Today is <%= new Date() %> </BODY> </HTML> Scriptlet Expression

interprétation script Coté serveur <HTML> <BODY> <%="Hello world !"%> <script type="text/javascript"> <!– var now = new Date(); document.write("today is " + now.getDay()); //--> </script> </BODY></HTML> Vue utilisateur interprétation serveur Hello world Today number is 19 Coté client JSP est différent de javascript qui est interprété sur le poste client Une page HTML qui mixe javascript et JSP (ou PHP) est complexe à lire et à comprendre <HTML> <BODY> Hello world ! <script type="text/javascript"> <!– var now = new Date(); document.write("today is " + now.getDay()); //--> </script> </BODY></HTML> interprétation client

variables prédéfinies JSP out : flux de sortie dans la réponse HTTP au client. utiliser println() request : objet représentant la requête HTTP utiliser getParameter("name"), getCookies(), forward() response : objet représentant la réponse HTTP out est retournée par response.getWriter() utiliser setCookie(new Cookie("name","value")) session : objet représentant la session HTTP utiliser setAttribute("name"), getAttribute("name"), removeAttribute("name") La session de l’utilisateur est retourner par request.getSession(false) request.getSession(true) crée et retourne une nouvelle session (déconnexion ou logout) pageContext : objet représentant le contexte d'une page Facilite l'accès au contexte de l'application web utiliser setAttribute("name") pour donner des paramètres aux taglibs Utiliser foward("url") pour déléguer la réponse à une autre page

formulaire et JSP Champs des formulaires directement dans des variables : <FORM ACTION="test.jsp" METHOD="POST"> Votre nom : <INPUT TYPE=TEXT NAME="nom"> Votre âge : <INPUT TYPE=TEXT NAME="age"> <INPUT TYPE=SUBMIT VALUE="Ok"> </FORM> Dans test.jsp, l’objet request contient les saisies: <% request.getParameter("nom") request.getParameter("age") %> On peut écrire en réponse dans test.jsp: ... Bonjour <% out.println(request.getParameter("nom")); %>

syntaxe JSP <% … %> : scriptlet <%! … > : déclaration servlet <%! int myVariable = 0; %> <%-- Voici un commentaire JSP --%> <%= … %> : expression (pas de ; final) <%@... %> : directive <%@page import="…", <%@include page="url" <jsp:…> : tag jsp <jsp:include>, <jsp:forward> TagLib JSTL <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> Autres TagLib : Struts2, Tiles, Spring MVC, etc. Librairie URI Préfixe core http://java.sun.com/jsp/jstl/core c Format http://java.sun.com/jsp/jstl/fmt fmt XML http://java.sun.com/jsp/jstl/xml x SQL http://java.sun.com/jsp/jstl/sql sql Fonctions http://java.sun.com/jsp/jstl/functions fn Préferer le scriplet java plutôt que <core:…> Ne pas utiliser <sql:…> pour respecter l’architecture 4 tiers Format pour le i18n, l’affichage et l’interprétation des dates, nombres, messages, les encodages XML pour interpréter des fichiers xml façon XPATH FN : pour les fonctions utilitaires (façon StringUtils) Voir http://www.jmdoudoux.fr/java/dej/chap-jstl.htm et http://adiguba.developpez.com/tutoriels/j2ee/jsp/jstl/

Forward vs redirect Forward utilisable dans un même war Redirect sinon <jsp:forward page="/jsp/welcome.jsp"/> Page A Page B Page C Forward compliqué à faire en servlet, seul <jsp:forward> permet de donner des paramètresen retour comme par exemple un message d’erreur Pour un forward les objets request et response sont retransmis (ne rien mettre dans « out ») Pour un redirect les paramètres de la request sont perdus sauf si ils sont remis dans la queryString, pour le navigateur fasse le réenvoie le redirect est plus long mais permet un envoi vers un autre conteneur web totalement indépendant. forward this.getServletConfig().getServletContext().getRequestDispatcher( "/JSP/Demo.hello.jsp").forward(request,response);

Forward pour les erreurs Page1.jsp Nb pizza incorrect … <% if (nbPizza<=0) { %> <jsp:forward page="Page1.jsp"> <jsp:param name=”errMsg" value=”Nb pizza incorrect" /> </jsp:forward> <% } %> -2 Page 2.jsp

Utilisation des taglibs 1/2 Rajout des jars correspondant dans WEB-INF/lib WEB-INF/lib/jstl.jar WEB-INF/lib/standard.jar Exemple : <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <html><body> <% pageContext.setAttribute("now",new java.util.Date()); %>" … <fmt:formatDate pattern="yyyy-MM-dd" value="${now}" /> … </body></html> Les jar de JSTL sont à rajouter en fonction des conteneurs web Depuis Servlet API 3.0 les tld de la JSTL ne sont plus à déclarer dans web.xml Uri ".../jsp/jstl/..." obligatoire pour indiquer JSTL 1.1 dans JSP 2.0

Utilisation des taglibs 1/2 … code HTML … <jsp:useBean id=“user” class=“com.acme.EndUser” scope=“session” /> <? user.setName(“Dupont”); ?> <h2>Welcome, <c:out value="${user.name}”/> Ou <? EndUser user = new EndUser(); user.setName(“Dupont”); ?> <h2>Welcome, ${user.name}”

Conteneur Web couche de persistance JDBC – Transaction

Architecture webapp

Java DataBase Connectivity Librairie d’interfaces java qui définisse la communication avec une base de données Package « java.sql » classe « DriverManager », interface « Driver » démarrage d’une connexion interfaces « Connection », « DatabaseMetaData » Gestion d’une connexion et création de requêtes SQL interface « Statement » et spécialisations gestion, exécution d’une requête SQL interfaces « ResultSet », « ResultsetMetaData » gestion des résultats de requête SQL Application Java JDBC DriverManager MySQL JDBC Driver Oracle JDBC Driver Voir la javadoc MySQL Oracle

Connexion via JDBC Classe DriverManager Temps d'exécution long DriverManager.getConnection(url,user,password) Interface « java.sql.Connection » Gère la connection à la base close(), getMetaData() Création d'une nouvelle requête Statement stmt = createStatement(); prepareStatement("select a from b where c=?") pour optimisation, ‘ ? ’ = paramètre, ordre important prepareCall("? = call proc_stock[?,?]") procédure stockée (attention à la portabilité !) Gestion du transactionnel commit(), rollback(), setAutoCommit(boolean) Temps d'exécution long À considérer comme monothread Obtenir une connexion est un processus couteux : utiliser des pools dans une DataSource Préférer prepareStatement() à createStatement() lorsque les requêtes ne change pas La spécification JDBC indique qu'une java.sql.Connection est monothread mais pour une gestion des transactions plus sur il est préférable de la considérer monothread. Pour vérifier les performances des méthodes : java -Xrunhprof:cpu=sample,depth=15,file=prof0.txt MaClasse0

Exemple de connexion /** retourne une connection à une base de données accessible via JDBC * @param dbURL - URL de la base de données * @param driverClassName - nom complet de la classe qui sert de driver JDBC * @param user - nom de compte utilisateur de la base de données * @param password - mot de passe associé au compte utilisateur */ public Connection connect(String dbURL, String driverClassName, String user, String password) throws Exception { // configure le DriverManager pour charger le driver try { Object drv = Class.forName(driverClassName).newInstance(); } catch( Exception e) { e.printStackTrace(); throw e; } Connextion connection = null; connection = DriverManager.getConnection(dbURL, user, password); return connection; } catch( SQLException se) { se.printStackTrace(); throw se; } } Le jar du driver doit être dans le classpath Ne jamais avoir de bloc catch vide : printStackTrace est le minimum Throw e plutôt que return null

Exemple de update Connection cnx = DriverManager.getConnection("jdbc:mysql://localhost:3306/pizzadb","com.mysql.jdbc.Driver","user","****"); PreparedStatement updateVentes = cnx.preparedStatement( "UPDATE CAFE SET VENTE = ? WHERE NOM_CAFE LIKE ?"); updateVentes.setInt(1,50); updateVentes.setString(2, "Colombian"); updateVentes.executeUpdate(); Statement stt = cnx.createStatement(); stt.executeQuery("UPDATE CAFE SET VENTE = 50 WHERE NOM_CAFE LIKE 'Colombian' "); Un prepareStatement est optimisé pour de nombreux appels à la base de données.

Requêtes via JDBC « Statement » représente une requête Exécution d’une requête SQL Resulset res = statement.executeQuery("select …"); int nbRows = statement.executeUpdate("update …"); Pagination des résultats setMaxRows(n), getMoreResults() contrôle de l’exécution de la requête setQueryTimeout(int seconds), cancel() PreparedStatement, CallableStatement set<Type>(n°param,valeur) avec pour <Type> : String, Long, Double, BigDecimal, Boolean, Date, etc.

Résultats via JDBC « Resultset » représente le résultat d’une requête méthodes principales : get<Type>(nom_colonne) next() exemple: while(rst.next()) { … gestion d ’une ligne … } getMetaData() « ResultsetMetaData » décrit le résultat (= la table si « select * ») getColumnCount(), getColumnType() isNullable(), getColumnLabel(), etc.

Exemple de insert MySQL Pizza p = new Pizza("royale","tomato"); Statement stt = cnx.createStatement(); int nbLigneCrees = stt.executeUpdate("INSERT INTO pizza (pizza_name,pizza_type) VALUES ('"+p.getPizzaName()+"','"+p.getPizzaType()+"')", Statement.RETURN_GENERATED_KEYS); ResultSet generatedKeys = stt.getGeneratedKeys(); if (generatedKeys.next()) { p.setId(generatedKeys.getLong(1)); } L'identifiant (colonne id) est généré automatiquement par la base de données MySQL, getGeneratedKeys permet de récupérer cet identifiant. MySQL ALTER TABLE pizza CHANGE pizza_id pizza_id BIGINT( 20 ) NOT NULL AUTO_INCREMENT

Exemple de select ... chatRooms.add(chatRoom); } // affiche les noms des cplonnes puis chaque ligne de résultat de la requête Statement stmt = connection.createStatement(); ResultSet rst = stmt.executeQuery("select c.chatRoomName, t.topicName, c.language, from ChatRoom c, TopicCategory t where c.topicCategoryId = c.Id order by topicName, chatRoomName"); ResultSetMetaData rstData = rst.getMetaData(); Collection<ChatRoom> chatRooms = new Vector<ChatRoom>(); while(rst.next() == true) { ChatRoom chatRoom = new ChatRoom(); chatRoom.setRoomName(rst.getString("chatRoomName")); ... chatRooms.add(chatRoom); } // fermeture de la requête et de ses Resultset associés stmt.close();

Transactions sous MySQL Transactions en SQL BEGIN, COMMIT, ROLLBACK, CHECKPOINT option AUTOCOMMIT Note : les DDL (create, alter, drop table) sont toujours AUTOCOMMIT Accès concurrents : ligne ou table bloquée jusqu’au commit ou rollback LOCK TABLE SELECT … FOR UPDATE Gestion optimistes des accès concurrents Moteurs pour la base MySQL InnoDB : foreign keys, select for update, stockage optimisé MyISAM : plus rapide en lecture MEMORY : pas de stockage sur le disque NDBCluster : table répartie sur plusieurs serveurs

Illustration d’une transaction Table possessions (d’actions par utilisateurs) Table comptes Scénario 1 : l’utilisateur A achète 200 actions Axa à l’utilisateur B pour 37 euros id action quantite cote utilisateur version 1 Total 200 149,90 C 2 Axa 500 36,50 B 3 EDF 150 82,20 A 4 id solde utilisateur 1 3200 A 2 1540 B 3 2030 C Exemple transaction : achat/vente action en bourse Etapes transactions : update possessions set quantite=quantite-200 where id=2 insert into possessions (action,quantite,cote,utilisateur) values (‘AXA’,200,37,A) update comptes set solde=solde-1850 where utilisateur=A update comptes set solde=solde+1850 where utilisateur=B Exemple accès concurrent : double achat simultanée sur le même utilisateur pour la même action : rajouter une colonne updateCount (ou couple stampLogin, stampDate)

gestion optimiste des accès concurrents Scénario 1 Scénario 2 : l’utilisateur C achète aussi 400 actions Axa à l’utilisateur B pendant le scénario 1 id action quantite cote utilisateur version 1 Total 200 149,90 C 2 Axa 300 36,50 B 3 EDF 150 82,20 A 4 id action quantite cote utilisateur version 1 Total 200 149,90 C 2 Axa 500 36,50 B 3 EDF 150 82,20 A 4 id solde utilisateur 1 1350 A 2 3390 B 3 2030 C Exemple transaction : achat/vente action en bourse Etapes transactions : update possessions set quantite=quantite-200 where id=2 insert into possessions (action,quantite,cote,utilisateur) values (‘AXA’,200,37,A) update comptes set solde=solde-1850 where utilisateur=A update comptes set solde=solde+1850 where utilisateur=B Exemple accès concurrent : double achat simultanée sur le même utilisateur pour la même action : rajouter une colonne updateCount (ou couple stampLogin, stampDate)

Exemple de transaction JDBC cnx.setAutoCommit(false); PreparedStatement updateVentes = cnx.prepareStatement( "UPDATE CAFE SET VENTE = ? WHERE NOM_CAFE LIKE ?"); updateVentes.setInt(1,50); updateVentes.setString(2, "Colombian"); updateVentes.executeUpdate(); PreparedStatement updateTotal = cnx.prepareStatement( "UPDATE CAFE SET TOTAL = TOTAL + ? WHERE" + "NOM_CAFE LIKE ?"); updateTotal.setInt(1,50); updateTotal.setString(2,"Colombian"); updateTotal.executeUpdate(); cnx.commit(); Cet exemple ne gère pas les accès concurrents

Introduction au système de trace coté serveur Log4j Introduction au système de trace coté serveur

Log4j Librairie de génération de traces dans un fichier Utiliser des fichiers de log au lieu de System.out Types de traces : ERROR, INFO, DEBUG Installation : log4j-<version>.jar dans le CLASSPATH Logger : générateur de la trace Appender : destination de la trace LayoutPattern : format de la trace Configuration Log4j.properties Log4j.xml Voir http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

Exemple de config. log4j <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> <appender name="ConsoleAppender" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d %t %c{2} - %m%n"/> </layout></appender> <category name="fr.isen"> <priority value="DEBUG"/> </category> <root> <priority value="ERROR"/> <appender-ref ref="ConsoleAppender"/> </root></log4j:configuration> Voir http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

Exemple de code log4j public class DAOBase { ... final static Logger logger = Logger.getLogger(DAOBase.class); public void aMethod() { connection = DriverManager.getConnection(dbURL, user, pwd); if(logger.isDebugEnabled()) { logger.debug("connected to " + dbURL); } ....

Introduction aux tests unitaires et à l'intégration continue Junit Introduction aux tests unitaires et à l'intégration continue

JUnit Cadriciel de création de tests unitaires Génération de tests unitaire possible depuis Eclipse Un test unitaire teste une méthode ou une fonction différent des tests fonctionnels qui testent les fonctions de l’application, Lancement possible depuis Eclipse Code à isoler en gestion de configuration sous « src/test »

Exemple de junit Connection cnx = null @Before import static org.junit.Assert.*; import org.junit.Test; public class StringTest { @Test public void testConcatenation() { String foo = "abc"; String bar = "def"; assertEquals("abcdef", foo + bar); } public void testStartsWith() { assertTrue(foo.startsWith("ab")); Connection cnx = null @Before public void setUp() throws Exception { cnx = new DAOBase().getConnection( dbUrl,dbDriver, dbUser, dbPassword); } avec equals() @Test(expected = NullPointerException.class) public void methodCallToNullObject() { Object o = null; o.toString(); }

Méthode d’assertion Méthode Rôle assertEquals Vérifie que deux objets sont égaux, avec la méthode equals() assertFalse Vérifie que l'expression est fausse assertNotNull Vérifie que l'objet n'est pas nul assertNotSame Vérifie que deux références ne sont pas les mêmes assertNull Vérifie qu'un objet est nul assertSame Vérifie que deux références sont les mêmes, avec l’opérateur == assertTrue Vérifie que l'expression est vrai fail Provoque l'échec du test

Junit depuis Eclipse Création : bouton droit sur une classe, puis New, Other, Java, Junit, TestCase Génerer le code de test sous un autre répertoire « /test » Utilisation : bouton droit sur une Junit puis Run As, Junit Test menu depuis Eclipse : clique bouton droit sur une classe, puis New, Other, Java, Junit, TestCase

Tests unitaires Un test unitaire teste une méthode ou une fonction différent des tests fonctionnels qui testent les fonctions de l’application, Tests unitaires automatisés  lancés après la construction d’un exécutable Utilisés pour l’intégration continue Tests unitaires d’intégration lancés après l’installation d’une application Fonctionnement interne Fonctionnement de l’IHM Compilation Tests unitaires Documentation Contrôle qualité Déploiement

Processus de l’intégration continue Les développeurs livrent leurs modifications en continu 2 A intervalle régulier l’état du référentiel de sources est vérifié 3 En cas de modifications, l’usine logicielle procède à la construction du projet Référentiel des sources SCM 1 Vérification de l’état du référentiel Livraison de code Compilation Génération de documentation Récupération des sources Exécution des tests unitaires Packaging et déploiement Calcul de métriques qualité Log4J - JUnit Développeurs 6 Consultation des métriques qualité Notifications Parler des MockObject pour rendre possible les Lancement depuis Ant Lancement depuis Maven Rapport de couverture de code avec EMMA 4 En cas d’échec, la résolution du problème devient la priorité de l'équipe Usine logicielle 5 Testeurs Environnement de développement, d’intégration ou de recette Déploiement 7 Tests

Introduction à l'informatique distribué et à RMI JNDI Introduction à l'informatique distribué et à RMI pour expliquer les DataSources

Objets distribué Prinpices : Faire coopérer des logiciels entre eux Avoir des "variables globales" au réseau Utiliser et répartir la puissance de calcul et de stockages sur plusieurs serveurs Appeler une méthode d'un objet se trouvant sur une autre machine exactement de la même manière que s’il se trouvait au sein de la même machine Pouvoir retrouver un objet existant d'après son « nom » Client Serveur ObjetStub ObjetServant Middleware

Comment sont vu les objets. Mode classique Mode distribué Machine 1 Machine 1 Machine 2 Interface Implementation Squeleton Stub Objet Application Application

Utilisation de l'annuaire 3 - Appel l'objet Client Serveur 2- Recherche un objet Object o = envCtx.lookup("MyObj"); 1- Déclare un objet Annuaire

Technologies Objets distribués Responsable RPC IETF C, C++ CORBA OMG tous RMI Oracle (ex Sun) java SOAP (WebService) W3C WCF Microsoft .Net HTTP+REST+XML/JSON ?, pas de norme IETF : Internet Engineering Task Force, éditeur des RFC qui normalise Internet WCF : Windows Communication Framework : remplace COM+, DCOM et WSE RPC, XML-RPC, REST ne sont conformes à la programmation orienté objet

Java RMI Remote Method Incocation Permet à du code client d'appeler une méthode sur un objet serveur Java distant. simplification de CORBA pour java uniquement. Générateur de code Stub et Skeleton à partir d'une interface : rmic Annuaire d'objet serveur disponible rmiregistry Package java.rmi Disponible dans Java SE

JNDI Java Naming and Directory Interface Service de nommage / annuaire pour JEE API accès aux annuaires javax.naming « Service Provider » par annuaire cible (LDAP, NIS, RMI registry…) Utiliser dans JEE pour accéder à des DataSources UserTransaction EJB Etc. JEE est une évolution de CORBA pour Java

Déclarer une DataSource dans Tomcat $tomcat/webapps/myapp/META-INF/context.xml <Resource name="jdbc/PizzaDB" auth="Container" type="javax.sql.DataSource" username="root" password="root" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/pizzadb" maxActive="8" maxIdle="4"/> $tomcat/webapps/myapp/WEB-INF/web.xml <resource-ref> <res-ref-name> jdbc/PizzaDB </res-ref-name> <res-type> javax.sql.DataSource </res-type> <res-auth> Container </res-auth> </resource-ref> Création d’une DataSource dans Tomcat Utilisation d’une DataSource Voir http://tomcat.apache.org/tomcat-5.5-doc/config/context.html Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); DataSource ds = (DataSource) envCtx.lookup("jdbc/PizzaDB");

Construction de livrables Ant - Maven

Ant http://ant.apache.org Outil pour construire un livrable jar, war, ear Remplace les fichiers "make" Intégrer à Eclipse (démarrage, configuration) Doc. sous $ANT_HOME/docs/manual/index.html et http://ant.apache.org/manual/tasksoverview.html Suite sur le support de cours Ant de T. Dandelot Parler de la tache <env> et insister sur la tâche <war>, montrer le build.xml tu TP pour certains exemples

EJB Session – JPA – JMS/MDB pour expliquer les DataSources

EJB Enterprise Java Beans Cadriciel de logique métier coté serveur S’appuie sur Java SE et les APIs de Java EE JNDI, JTA/JTS, JDBC, JMS, JAAS Gestion déclarative : personnalisation par annotations (@... dans le code) ou descripteur de déploiement (xml) "Portable" sur les différents conteneurs EJB Les descripteur de déploiement permettent de ne pas toucher au code source

Architecture 4 tiers JEE WEB Container T2 Browser T1 Servlets JSPs HTTP JDBC JMS JTA JCA JAAS JavaMail JNDI … html T4 jdbc DB T1+T2 RMI / IIOP Appel local JVM Applets java/flash T3 SOAP, REST RMI / IIOP EJBs xxxx SOAP ou REST = WebSercices, utilisables sur Internet RMI / IIOP = CORBA, utilisables sur un réseau privé (pb de bande passante et de pare-feu) public static void main(…) { T1+T2 T4 EIS EJB Container Java Application Java EE Application Server

Services du conteneur d'EJB Annuaire de composants EJB et de ressources Grappe de ressource (pool) Transactions Persistance Répartition de charge Sécurité C'est pour bénéficier de tout ces services technique qu'il est opportun d'utiliser JEE (les EJB pour les 4 derniers) L'ensemble des services fournis par le conteneur EJB focalise le développeur sur le métier

interface d'un EJB Déclare l'annotation @Remote Déclare les méthodes métier C'est une vue cliente et distante de l’EJB Paramètres passés par copie Retour et exceptions également Doivent implémenter Serializable import javax.ejb.Remote; ... @Remote public interface PizzaManager { public Long orderPizza(PizzaOrder po, EndUser eu); Parler de la différence avec le passage de paramètre par référence Il existe @Local et @LocalBean mais il est préférable de ne pas les déclarer en EJB dans ce cas (les traiter comme des POJO, où alors utiliser Spring IoC pour un couplage plus lâche)

Implémentation d'un EJB Implémente les méthodes de l’interface Remote Peut hériter d’un autre EJB, ou d’un POJO Spécifie les caractéristiques de déploiement par annotations type d'EJB (Stateless, Stateful, Message) transactions, sécurité, persistance webservice POJO : Plain Old Java Object La persistance sera vue avec JPA Les WebServices se font par l'annotation @WebService dans une classes puis WebMethod dans une méthode dans un EJB pour un contaneur EJB ou un POJO dans un conteneur web Voir ftp://ftp-developpez.com/tahe/fichiers-archive/tutoriel-webservice-netbeans65-glassfish.pdf

Exemple de code Serveur Client distant Client local @Stateless(mappedName="PizzaManager") Public class PizzaManagerBean implements PizzaManager { public Long orderPizza(PizzaOrder po, EndUser eu) { ... Client distant Context ctx = new InitialContext(); PizzaManager pm = (PizzaManager)ctx.lookup( "java:global/PizzaEAR/PizzaFrontOffice/PizzaManagerBean"); ... pm.creatPizzaOrder(po); @EJB(mappedName="PizzaManager") private PizzaManager pizzaMgr; // Injection d’EJB local Client local @EJB(name="PizzaManager") private PizzaManager pizzaMgr; // Injection d’EJB local

EJB Session Réalisation d’actions sur demande de clients Objets métier gestionnaire non persistants Ce n'est pas une entité métier sauver en base de données Session Stateless ou Stateful Un Bean Stateful gère un l’état il est plus difficile de le dupliquer Un EJB Session est une sorte de contrôleur, un point d'entrée façade dans l'application @Stateful crée un EJB Session avec gestion de l'état, réplicas plus couteux : exemple EJB de compteur incrementeCommande()

Caractéristiques de déploiement Stateless Session Bean Grappe d’instances possible Appels de méthodes " idempotent " Stateful session / Activation / Passivation @PostActivate après activation @PrePassivate avant passivation Pour tous les Session Beans Callbacks @PostConstruct et @PreDestroy @TransactionManagement(value=TransactionManagementType.BEAN) @RolesAllowed("front-office","back-office"} ) un EJB est accessible en local via injection de dépendance @EJB sur l'attribut client ou via un lookup() vers java:global/<bean> ou java:module/<bean> ou java:app/<module-name>/<bean> ou un autre espace de nom spécifique à un conteneur d'EJB

EJB : Configuration & Déploiement Descripteur de déploiement : META-INF/ejb-jar.xml <enterprise-beans> Description du Bean (Stateful, Stateless, ...) Ressources (Base de données,...) Securité: permissions et rôles Transactionnels </enterprise-beans> Priorité au descripteur de déploiement sur les annotations.

Descripteur de déploiement (optionnel) Bean Session Lien entre interfaces et implémentation <enterprise-beans> <session> <description>EJB PizzaShop</description> <ejb-name>PizzaManager</ejb-name> <business-remote>...PizzaManagerRemote</business-remote> <ejb-class>...PizzaManagerBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Bean</transaction-type> <resource-ref> <res-ref-name>jdbc/facturationDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref> </session> </enterprise-beans> Bean ou Container BeanManaged transaction : le développeur utilise l'API de UserTransaction UserTransaction utx = context.getUserTransaction(); utx.begin(); utx.commit(); utx.rollback(); ContainerManaged transaction : spécifié pour chaque méthode Ressource : ici, base de données

Injection de dépendances Variable d’instance initialisée par le conteneur Alternative au lookup JNDI Interne à une application JEE serveur uniquement Dans un client d'EJB (par exemple une Servlet) @EJB(mappedName="java:global/PizzaEAR/PizzaFrontOffice/Pizz aManagerBean") private PizzaManager pizzaMgr; // Injection d’EJB local Dans l'EJB @Resource(name="java:/PizzaDS") javax.sql.DataSource ds; // Injection de ressource via nom JNDI L'injection de dépendance est également utilisé pour le contexte de persistance JPA Java EE6 à introduit l'annotation @Inject

Gestion des erreurs Exception métier Exception technique L'utilisateur est la cause de l'erreur ou peu la résoudre Le développeur doit créer des exception métier qui : héritent de java.lang.RuntimeException Utilisent l'annotation @ApplicationException(rollback=true) Exception technique Réutiliser les exceptions disponibles ServletException, dans les servlets et JSP EJBException dans les EJB SQLException dans les DAO @ApplicationException(rollback=true) public class BusinessException extends RuntimeException { .... Exemple de business exception : "il n'y a plus de pizza en stock" ou "l'utilisateur final n'a pas assez d'argent"

Packaging EAR /lib EAR JAR JAR JAR EJB-JAR EJB-JAR WAR http://localhost:8080/Pizza/ /META-INF/application.xml <application><display-name>PizzaEAR</display-name> <module><ejb>PizzaEJB.jar</ejb></module> <module> <web> <web-uri>PizzaFrontOffice.war</web-uri> <context-root>Pizza</context-root> </web> </module> </application>

Rappel sur le chargement de classes Les classloaders sont hiérarchisés Règle : Cherche la classe dans le cache de son niveau Demande la classe au classloader parent Si ClassNotFoundError pour le parent alors cherche la classe à son niveau Si toujours pas trouvé alors ClassNotFoundError Hierarchie standard (hors JEE), du pères aux fils Bootstrap : java.* Extension : $JRE_HOME/ext/*.jar System (ou application si non JEE) : $CLASSPATH

Gestion du classpath JEE Module Classpath EAR All JARs in the /lib directory of the EAR Manifest Class-Path of any JARs in 1 EJB-JAR EJB-JAR file itself JARs referenced by manifest Class-Path of EJB-JAR JARs referenced by manifest Class-Path of above JARs (in 2) WAR WEB-INF/classes JARs in WEB-INF/lib JARs referenced by manifest Class-Path of WAR JARs referenced by manifest Class-Path of JARs in 2 and 3 Retour à la ligne obligatoire ! Le chemin de classpath est relatif à l'emplacement disque du jar ou du WAR dans l'EAR (espace pour séparer jar Rappel de l'ordres de chargement des classes : Bootstrap : java.* Extension : $JRE_HOME/ext/*.jar System : $CLASSPATH Voir aussi http://www.developer.com/java/ejb/article.php/10931_3670496_2/Packaging-EJB-3-Applications.htm Exemple : META-INF/MANIFEST.MF de Pizza.war dans Pizza.ear Class-Path: lib/PizzaBiz.jar PizzaEjb.jar lib/log4-j1.2.16.jar lib/jackson-databind-2.0.6.jar lib/jackson-core-2.0.6.jar

Répartition de charge : notations Un noeud (machine) qui héberge un ou plusieurs serveurs web ejb Un conteneur Web Un conteneur EJB ejb web Un serveur qui héberge un conteneur Web Un serveur qui héberge un conteneur EJB ejb web Un serveur qui héberge un conteneur Web et un conteneur EJB Apache mod_jk Un serveur Apache avec le module mod_jk

Répartition de charge : scenarii (1) Répartition du serveur JavaEE Compact Réparti (au sein d ’un même nœud) Réparti ejb web web ejb web ejb

Répartition de charge : scenarii (2) (1) web ejb ejb web Apache mod_jk Réplication session http Apache mod_jk Répartition de charge EJB ejb web web ejb (3) (4) mod_jk mod_proxy mod_balancer web web ejb Apache mod_jk ejb Apache mod_jk web web ejb

Répartition de charge depuis un load balancer Cette technique fonctionne aussi avec des sites PHP

Gestion des transactions Utilisation de JTA javax.transaction.UserTransaction Contrôle de la transaction (timeout, « rollbackOnly ») Exemple : UserTransaction utx = (UserTransaction) ctx.lookup("java:comp/UserTransaction"); utx.begin(); … utx.commit();

Gestion déclarative des transactions Au niveau de la méthode de l'EJB Required (valeur par défaut) Si pas de transaction, nouvelle transaction Supports Si transaction courante, l’utiliser NotSupported Si transaction courante, elle est suspendue RequiresNew Nouvelle transaction (s'il y a un transaction courante, elle est suspendue) Mandatory Exception si pas de transaction courante Never Exception si transaction courante

Gestion déclarative des Transactions par annotations @TransactionManagement(javax.ejb.TransactionManagementType.CONTAINER) public class Facturation implements FacturationRemote { @TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRED) public void creerFacture( ) { // … } NotSupported Required RequiresNew Mandatory Supports Never

Descripteur de déploiement : Gestion déclarative des Transactions par xml <assembly-descriptor> <container-transaction> <method> <ejb-name>Facturation</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> ... </assembly-descriptor> NotSupported Required RequiresNew Mandatory Supports Never

Persistance + Transactions DB1 Conteneur EJB EJB1 no cust DB2 T1 T2 DD EJB JMX REG DBM 2-phase commit server2 Conteneur EJB EJB2 Conteneur WEB Servlet http JTM JMX EJB DBM JMX Web Appli client server1 server3

JPA Framework : Hibernate, EclipseLink, ObjectDB, OpenJPA Java Persistence API Un diagramme de classes métier correspond à un modèle de base de donnée relationnel Annotations de correspondance objet-relationnel Déclaration des tables et colonnes correspondantes Déclaration des associations Déclaration de l'héritage Utilisation de JPA dans le code java Framework : Hibernate, EclipseLink, ObjectDB, OpenJPA Alternatives : JDO, JDBC

Annotations JPA Annotations à insérer dans les classes métier pour définir le mapping objet relationel Annotations JPA Classe métier : @Entity @Table(name="<nom_table>") @MappedSuperClass : pour les classes mère abstraites Attributs dans classe métier : @Column(name="<nom_colonne>", length=<taille>, nullable=<true|false>) @Id : la colonne est l’identifiant unique de la table @GeneratedValue : valeur non fournie par le développeur @Version : colonne technique utilisée pour la gestion optimiste d’accès concurrents @Transient : ignoré par JPA (non sauvé) L'annotation peut se faire sur l'attribut ou sur la méthode getter Surcharger une définition dans une class mère : @AttributeOverride(name="id", column=@Column(name="pizza_id"))

Exemple 1/2 Associations @Entity @Table(name="pizzaorder") public class PizzaOrder implements Serializable { // Serializable conseillé public PizzaOrder () { } // Constructeur par défaut obligatoire @Id @GeneratedValue(strategy=GenerationType.IDENTITY) public Long id; @Column(name="order_date") private Date orderDate; @ManyToOne(fetch=FetchType.LAZY,cascade=CascadeType.REFRESH) @JoinColumn(name="enduser_id") protected EndUser customer; ___________________________________ @Table(name="enduser") public class EndUser implements Serializable { ... @OneToMany(mappedBy="customer", cascade=CascadeType.ALL, fetch=FetchType.LAZY) private Collection<PizzaOrder> pizzaOrders; Pour MySQL Autoincrement Nom de colonne différent Une classe entity ne doit pas être final Associations (1 EndUser , N PizzaOrder)

Associations Exemple : EndUser OneToMany PizzaOrder Le « propriétaire » de la relation correspond à la table qui possède la clé étrangère Lien EndUser/PizzaOrder : PizzaOrder est « propriétaire » de la relation Attribut « mappedBy » côté EndUser, et joinColumn côté PizzaOrder OneToOne Exemple : EndUser et Address OneToMany Exemple : EndUser vers PizzaOrder ManyToOne Exemple : PizzaOrder vers EndUser ManyToMany Exemple : Pizza et PizzaOrder

Jointures en JPA Q: Pas de cascade avec LAZY loading… donc EAGER ? @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="<nom_colonne>", unique=true, nullable=true) @OneToMany(mappedBy="<nomAttributClasseAssociée>", cascade=CascadeType.ALL) @ManyToMany @JoinTable(name="<nom_table>", joinColumns = @JoinColumn(name ="<nom_colonne>"), inverseJoinColumns = @JoinColumn(name ="<nom_colonne>" ) OneToOne : idem ManyToOne d'un coté et OneToMany de l'autre CascadeType : ALL, MERGE, PERSIST, REFRESH, REMOVE, DETACH FetchType : LAZY, EAGER OneToMany CascadeType.ALL pour les compositions (rond plein) OneToMany CascadeType.REFRESH pour les aggrégations (rong creux) ManyToOne CascadeType.REFRESH en général Lazy loading à privilégier en OneToMany ALL CascadeType par défaut ? Q: Pas de cascade avec LAZY loading… donc EAGER ?

Cascade @ManyToMany(mappedBy="pizzas",cascade= ?) private Collection<PizzaOrder> pizzaOrders = null; CascadeType Effet ALL Tous les effets ci-dessous, valeur par défaut PERSIST Si l'entité à créer possède des entités dans l'association concernée, alors elles sont créées également MERGE Si l'entité à modifier possède des entités dans l'association concernée, alors celle-ci sont modifiées (ou créées) également REMOVE Si l'entité à supprimer possède des entités dans l'association concernée, alors celle-ci sont supprimées également REFRESH Si l'entité à relire possède des entités dans l'association concernée, alors celle-ci sont relues également ("undo" des modifications) DETACH Si l'entité à détacher possède des entités dans l'association concernée, alors celle-ci sont détachées également Les cascades ne fonctionnent que pour un fetch=FetchType.EAGER quid si les entités d'une association fetch=FetchType.LAZY est lue quand même ? default cascadetype for fetched lazy items? READ N'existe pas ! car il s'agit du fetch=FecthType.EAGER NONE N'existe pas ! car il s'agit du fetch=FecthType.LAZY

Exemple 2/2 idem OneToMany d'un coté Facultatif, public class PizzaOrder implements Serializable { ... @ManyToMany(fetch=FetchType.LAZY) @JoinTable(name="pizzadetail", joinColumns=@JoinColumn(name="order_id"), inverseJoinColumns=@JoinColumn(name="pizza_id")) private Collection<Pizza> pizzas = null; .... __________________________ public class Pizza implements Serializable { @ManyToMany(mappedBy="pizzas") private Collection<PizzaOrder> pizzaOrders = null; idem OneToMany d'un coté Facultatif, Une classe entity ne doit pas être final

Configuration JPA La configuration de la persistance par JPA est dans META-INF/persistence.xml <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="PizzaPU"> <jta-data-source>java:/PizzaDS</jta-data-source> <class>fr.isen.eleve.todo.pizza.biz.EndUser</class> <class>fr.isen.eleve.todo.pizza.biz.Pizza</class> <class>fr.isen.eleve.todo.pizza.biz.PizzaOrder</class> <properties> <property name="showSql" value="true"/> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" /> <property name="hibernate.hbm2ddl.auto" value="validate" /> </properties> </persistence-unit> </persistence> Cet exemple utilise Hibernate, Hibernate est détenu par RedHat comme Jboss create : crée les tables au démarrage, create-drop : crée les tables au démarrage puis les supprimes à l'arrêt update : met à jour les tables au démarrage Validate : vérifie les tables au démarrage ou create, create-drop, update

Instructions JPA La classe EntityManager manipule les données em.flush() : sauvegarde immédiate des modifications em.refresh(e) : annulation de modifications em.createQuery(<requête en ejbQL avec :param >) em.createNativeQuery(<requête en SQL>) em.getTransaction().begin(); em.getTransaction().commit(); JPA SQL em.persist(e) insert em.merge(e) update em.remove(e) delete em.find(e.class,id) select EntityManagerFactory emf = Persistence.createEntityManagerFactory ("<persistanceunitname>"); EntityManager em = emf.createEntityManager(); @PersistenceContext(unitName="PizzaPU") private EntityManager em; L'écriture réelle en base de données est faite au commit() ou au flush() Parler de la notion d'instance attachée au persistenceManager

Gestion des entités obligatoire si CascadeType.ALL non défini ... public void orderPizza(PizzaOrder po, EndUser eu) { EndUser eu = persistenceManager.find(eu.getClass(),eu.getId()); po.setCustomer(eu); persistenceManager.persist(po); Refresh() et cascade d'entité non gérée interdite Non gérée si eu.id = -1 alors le find retournera null est le PizzaOrder ne sera associé à aucun EndUser Par contre si la ligne rouge n'existe pas et que nous sommes en CascadeType.ALL alors Il y aura une erreur IllegalStateException (org.hibernate.TransientObjectException avec Hibernate) car gérée persit(), merge(), find(), query() detach() garbage collector new

Exemple @Stateless public class FacturationBean implements FacturationRemote { @PersistenceContext private EntityManager entityManager; public void creerFacture(String numfact, double montant) { Facture fact = new Facture(numfact); fact.setMontant(montant); entityManager.persist(fact); } public Facture getFacture(String numfact) { return entityManager.find(Facture.class, numfact); }

Définition de l'héritage 1 seule table pour toutes les sous-classes @Entity @Inheritance(strategy=SINGLE_TABLE) @DiscriminatorColumn(name="<nom_colonne>", discriminatorType=STRING,length=20) Conseillé 1 table par sous-classe – classe mère @Entity @Inheritance(strategy=InheritanceType.JOINED) Déconseillé Voir http://openjpa.apache.org/builds/1.0.4/apache-openjpa-1.0.4/docs/manual/jpa_overview_mapping_inher.html Surcharger une définition dans une class mère : @AttributeOverride(name="id", column=@Column(name="pizza_id")) 1 table par sous-classe – classe fille @Entity @PrimaryKeyJoinColumn(name="ID", referencedColumnName="ID") 1 table par classe Classe mère abstraite @Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) @MappedSuperClass

EJB-QL Langage proche de SQL « select p from Pizza p » From sur les classes au lieu des tables Respectez la casse dans le nom de la classe (package facultatif) "update" et "delete" "inner join", "group by… having", "order by" public List<Facture> listFactures( ) { Query q = em.createQuery("select po from PizzaOrder fetch po.pizzas where po.customer.lastname like =:lastname"); q.setParameter("lastname","perez"); return q.getResultList(); } Liste des commanes avec leur client dont le nom commence par :lastname avec leur factures La jrequête retournera le PizzaOrder avec le customer et les pizzas en fonction du fetchType Possibilité de requête paramétrées et d'utiliser @NamedQuery Voir exemple sur http://docs.oracle.com/javaee/5/api/javax/persistence/NamedQuery.html ou q.getSingleResult() ou q.executeUpdate() selon les requêtes

Annotation de Callbacks d'une entitée Méthodes appelées par le persistenceManager Annotation de callback Description @PrePersist Avant insertion en base @PostPersist Après insertion en base @PreUpdate Avant mise à jour en base @PostUpdate Après mise à jour en base @PreRemove Avant suppression en base @PostRemove Après suppression en base @PreLoad Avant lecture en base @PostLoad Après lecture en base Il est utile de valider l'état d'un objet avant son insertion ou sa mise à jour en base

Bean Validation Déclaration de contrainte @NotNull @Size(max=50) public String getNom() Validation de données dans une instance Contraintes déclarées par annotations java String Int, Long Float, Double Date @NotNull @Min @DecimalMin @Future @Size @Max @DecimalMax @Past @Pattern Validation ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); Set<ConstraintViolation<DeveloppeurSeniorBean>> constraintViolations = validator.validate(personne); if (constraintViolations.size() > 0 ) { Voir http://blog.xebia.fr/2010/07/15/bean-validation/

Bonnes pratiques JPA Utiliser java.lang.Long pour l'id technique Utiliser java.util.Set pour les associations Toujours déclarer le type de fetch dans les associations Privilègier FecthType.LAZY sur toutes les associations Utiliser "join fetch" dans les requêtes JPQL Utiliser @NamedQuery Utiliser une Query d'update plutôt que t = em.find(Thing.class,id); t.setF(t); em.flush(); Définir les entités JPA puis générer les tables lorsqu'il n'y a pas d'existant Mais aussi distingués la clé technique de la clé fonctionnelle (id de Personne vs (nom,prenom,dateNaissance) écrire des méthodes equals() et hashCode() basée sur la clé fonctionnelle

Exemple @NamedQuery @Entity @Table(name="pizza") @NamedQueries( @NamedQuery( name="findAllPizzas", query="select p from Pizza p" ) public class Pizza implements Serializable {

Backup Slides

EJB versus API REST & WebService Les API REST fournissent des ressources API de type CRUD basée sur HTTP ou HTTPS avec XML ou JSON; portables entre plusieurs technologies (java, .Net, PHP, C++, etc.) ; adaptées au web (utilisation des verbes du protocole HTTP). Les WebServices fournissent des services fonctions plus évoluées que de simple CRUD, (services "métier") ; Avec des définition stricte (WSDL) qui facilite l'outillage et la génération de code; Portables entre plusieurs technologies (java, .Net, PHP, C++, etc.). Les EJB fournissent des services transactionnels distribués transactions (commit, rollback) réparties sur plusieurs serveurs ; Complété par des services techniques : sécurité, persistance, etc. limités à la technologie java limités au réseau local. Les normes WS-* augmentent progressivement le périmètre des WebServices à ceux des EJB et de CORBA CORBA a le même positionnement que les Web Services mais s'appuis sur IIOP/IDL au lieu de SOAP/WSDL WSDL, EJB et CORBA décrivent les interfaces + : Possibilité de généré des Stub et Skeleton + : Contrôles et sérialisation automatiques - : Rajout d'une couche au dessus de HTTP - : Rajout d'un overhead pour l'analyse automatique du message dans une librairie tierce l'API REST utilise souvent aussi une librairie de sérialisation JSON mais s'appui sur HTTP pour l'appel)

Déclaration de la sécurité par annotation @Stateful @RolesAllowed( { "frontoffice", "backoffice" } ) public class EndUserManagerBean ... L'identité (nom) d'un client est aussi appelée « Principal » Les rôles et les « Realm » (user /password) sont déclarés par configuration au niveau du serveur chaque serveur dispose de mécanismes spécifiques

Déclaration de la sécurité par DD <assembly-descriptor> ... <security-role> <description>Application front-office</description> <role-name>front-office</role-name> </security-role> <method-permission> <method> <ejb-name>EndUserManager</ejb-name> <method-name>authenticate,chgPassword</method-name> </method> </method-permission> </ assembly-descriptor> Définition de rôle Permissions accordées à un rôle

JMS

MDB Message Driven Bean EJB pour les appels asynchrones L'appelant n'attend pas la réponse pour continuer son travail Exécution sur réception d’un message Méthode onMessage( ) Utiliser les files de message JMS pour stocker les messages à traiter et les réponses Un serveur JEE fournis des files JMS Messages point à point : 1 émetteur, 1 destinataire Message publish/subscribe : 1 émetteur, n destinataires abonnés Garantie de stockage Garantie de livraison des messages Possibilité de retry

exemple MDB TX Appli : Client JMS JMS Serveur EJB Administration créer BD MDB StockHandler MDB Order Entity Bean Stock Mise à jour Envoi message Administration JMS Appli : Client JMS Topic Queue créer bind QCF JNDI publier Serveur EJB

exemple MDB (2) public class StockHandlerBean implements javax.jms.MessageListener { … public void onMessage(Message message) { ... sh = (StockHome)initialContext.lookup("java:comp/env/ejb/Stock"); queue = (Queue)initialContext.lookup("java:comp/env/jms/Orders"); MapMessage msg = (MapMessage)message; pid = msg.getString("ProductId"); qty = msg.getString( "Quantity"); cid = msg.getString("CustomerId"); Stock stock = sh.findByPrimaryKey(pid); stock.decreaseQuantity(qty); qs = session.createSender(queue); TextMessage tm = session.createTextMessage(); String m = "For CustomerId = "+cid+" ProductId= "+pid+" Quantity= "+qty; tm.setText(m); qs.send(tm); }

MDB : Annotations @MessageDriven(activationConfig = { @ActivationConfigProperty( propertyName="destination", propertyValue="SampleQueue"), @ActivationConfigProperty( propertyName="destinationType", propertyValue="javax.jms.Queue") }

Spring MVC Définition de la servlet dispatcher dans web.xml Annotations @Controller pour chaque classe Contrôleur @RequestMapping(value = "/chemin") return ModelAndView Taglib SpringMVC?

WebService et style de WSDL Encoding Message Literal Encoded RPC WSI-compliant type des paramètres non précisé : polymorphisme impossible Appel non validable par XSD : non WS-I compliant Polymorphisme possible dans les appels de SOAP Plusieurs appels de méthodes possibles en un seul appel SOAP Document méthode non précisé : un seule méthode par appel SOAP non WSI-compliant Polymorphisme impossible Choisir entre RPC/encoded sir la conformité WSI n'est pas importante (i.e. API privée) Sinon choisir Document/Litteral ou Document/Litteral avec l'option Wrapped @SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.BARE, style=SOAPBinding.Style.RPC,use=SOAPBinding.Use.ENCODED) @SOAPBinding(parameterStyle=SOAPBinding.ParameterStyle.WRAPPED, style=SOAPBinding.Style.Document,use=SOAPBinding.Use.LITERAL)

Configuration mod_proxy_balancer Répartition Simple et sans état <Proxy balancer://mycluster> BalancerMember http://192.168.1.50:80 BalancerMember http://192.168.1.51:80 </Proxy> ProxyPass /test balancer://mycluster Répartition simple avec affinité de session Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED <Proxy balancer://mycluster> BalancerMember http://192.168.1.50:80 route=1 BalancerMember http://192.168.1.51:80 route=2 ProxySet stickysession=ROUTEID </Proxy> ProxyPass /test balancer://mycluster

Répartition de charge depuis le serveur JEE TODO JBOSS Il est courant de rajouter une répartation de charge au niveau matériel/système d'exploitation avec des produits comme Veritas Cluster

Maven Projet défini dans une fichier POM pom.xml Arborescence de projet type Définition des dépendances entre projets <dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <version>3.1</version> <scope>test</scope> </dependency> Commandes de base : mvn clean, compil, package, install, tomcat:deploy Utilisable depuis Eclipse Suite sur le support de cours "introMaven" de C. Dumoulin

Spring IoC TODO : assemby.xml, context.xml Utiliser Jetty Assembler

Historique des WebServices vs CORBA CGI 1993 HTTP SOAP WSDL UDDI ebXML WSFL WS-Policy WS-PolicyAssertions WS-PolicyAttachment WS-Policy Framework WS-SecurityPolicy WS-SecureConversation WS-Discovery WS-Inspection WS-Eventing WS-Addressing WS-Routing WS-Referral MTOM WS-Enumeration WS-Transfer XML-RPC 1991 1998 2000 RPC CORBA EJB 1976 1991-2000 1999 XML-RPC est né du web et de RPC Les WebServices sont né en 1998 par l’association du web et de XML-RPC… et de la coupe du monde de football en France . Une solution mature de communication entre logiciels sur internet est disponible A partir de 2004, de nombreuses normes complémentaires sur des problématiques diverses sont apparues, avec des problèmes de cohérence entre elles. Par exemple, WS-Adressing remplace déjà 2 normes, il a diverses WS-Policy. C’est ce groupe de normes qui est appelé WS-*. RPC (Remote Procedure Call) est l’ancêtre de XML-RPC : il s’agit de la première solution de communication synchrone entre logiciels, le concept est née avec la naissance des réseaux informatique après ArpaNet (1971) et avant TCP/IP et Internet (1982). Le successeur officiel de RPC est CORBA (Common Object Request Architecture, réellement interopérable en 2000 avec CORBA 2.4), avec le protocole IIOP, protocole plus adapté aux réseaux locaux, et utilisé actuellement dans les EJB (1999) par exemple. Il me semble que CORBA et WS-* suivent une démarche de normalisation équivalente, CORBA pourrait aller sur le web. L’historique des protocoles de communication asynchrone comme SMTP (email) ou XMPP (chat) ne sont pas abordés dans cette présentation. Concurrency Naming Transaction Property Trading Security Externalization Persistence Life cycle Event Licensing Time 2004..