Introduction aux Web Services SOAP et REST
Introduction aux Web Services SOAP et REST
SOAP et
RESTful
Mohamed Youssfi :
med@[Link] ENSET,
Université Hassan II Mohammedia
med@[Link]
Exigences d’un projet
informatique
Exigences fonctionnelles:
◦ Une application est créée pour répondre , tout
d’abord, aux besoins fonctionnels des
entreprises.
Exigences Techniques :
◦ Les performances:
Temps de réponse
Haute disponibilité et tolérance aux pannes
Eviter le problème de montée en charge
◦ La maintenance:
Une application doit évoluer dans le temps.
Doit être fermée à la modification et ouverte à l’extension
◦ Sécurité
◦ Portabilité
◦ Distribution
◦ Capacité de communiquer avec d’autres applications distantes.
◦ Capacité de fournir le service à différents type de clients (Desk TOP,
Mobile, SMS, http…)
◦ …..
◦ Coût du logiciel
2
med@[Link]
Constat
Ilest très difficile de développer un système
logiciel qui respecte ces exigences sans utiliser
l’expérience des autres :
◦ Serveur d’application JEE:
JBOSS,Web Sphere,
GlassFish,Tomcat,
…
◦ Framework pour l’Inversion de contrôle:
Spring (Conteneur léger)
EJB (Conteneur lourd)
◦ Frameworks :
Mapping objet relationnel (ORM ) : JPA, Hibernate,Toplink, …
Applications Web : Struts, JSF, SpringMVC
….
◦ Middlewares :
RMI, CORBA : Applications distribuées
JAXWS pour Web services SOAP
JAXRS pour les Web services RESTful
JMS : Communication asynchrone entre les application
…
med@[Link]
Vision globale d’une architectures
Distribuées
SGB
D Entreprise 1 Entreprise 2 SGBD
Couche DAO
m
e
d
@
y
o
u
s
s
f
i
.
n
e
Architecture J2EE
Client Java RMI,
Serveur d’application J2EE
JM
Status=200
Déconnexion :Socket
[Link] IPC=…. [Link]
port=…
.
med@[Link]
Méthodes du protocole HTTP
Une requête HTTP peut être envoyée en
utilisant les méthodes suivantes:
◦ GET : Pour récupérer le contenu d’un document
◦ POST : Pour soumissionner des formulaires
(Envoyer, dans la requête, des données saisies
par l’utilisateur )
◦ PUT pour envoyer un fichier du client vers le
serveur
◦ DELETE permet de demander au serveur de
supprimer un document.
◦ HEAD permet de récupérer les informations
sur un document (Type, Capacité, Date de
dernière modification etc…)
med@[Link]
Le client envoie la requête : Méthode POST
Entête de la requête
corps de la requête
med@[Link]
Le client envoie la requête : Méthode GET
Entête de la requête
med@[Link]
Le Serveur retourne la réponse :
Entête de la réponse
HTTP/1.0 200 OK
Ligne de
Date : Wed, 05Feb02 [Link] GMT
Status Date du
Server : Apache/1.3.24
serveur Nom
Last-Modified : Wed 02Oct01
du Serveur
[Link]GMT Content-Type : Text/html
Dernière
Content-legnth : 4205
modification
*** saut de ligne ***
Type de
<HTML><HEAD>
contenu
….
Sa taille
</BODY></HTML>
a
Cobo </Body>
Compte
</ JaxW
l Envelope
>
-code : int
S -solde: double
Réponse
HTTP JaxB
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<Body>
<conversionResponse>
<return>132</return>
</conversionResponse>
</Body>
</Envelope>
Requête SOAP avec POST
Entête de la requête
Post /Nom_Script
HTTP/1.0 Accept:
application/xml Accept-
Language : fr
corps de la réponse
med@[Link]
Concepts des web services
Le concept des Web Services s’articule actuellement
autour des trois concepts suivants :
◦ SOAP (Simple Object Access Protocol)
est un protocole d'échange inter-applications indépendant de
toute plate-forme, basé sur le langage XML.
Un appel de service SOAP est un flux ASCII encadré dans des
balises XML et transporté dans le protocole HTTP.
service web
service WEB
Contrat
SOAP
3 : Quel est le format
d’appel du service que
1 : Je
tu proposes?
med@youssfi.
Structure d'un message
SOAP
med@[Link]
Mise en œuvre
des web services
avec JAX-WS
med@[Link]
JAX-WS
JAX-WS est la nouvelle appellation de JAX-RPC (Java API for XML
Based RPC) qui permet de développer très simplement des
services web en Java.
JAX-WS fournit un ensemble d'annotations pour mapper la
correspondance Java- WSDL. Il suffit pour cela d'annoter
directement les classes Java qui vont représenter le service web.
Dans l'exemple ci-dessous, une classe Java utilise des annotations
JAX-WS qui vont permettre par la suite de générer le document
WSDL. Le document WSDL est auto-généré par le serveur
d'application au moment du déploiement :
@WebService(serviceName="BanqueW
S") public class BanqueService {
@WebMethod(operationName="ConversionEuroToDh")
public double conversion(@WebParam(name="montant")double
mt){ return mt*11;
}
@WebMethod
public String test(){ return "Test";
} @WebMethod
public Compte getCompte(){ return new Compte (1,7000);
} @WebMethod
public List<Compte> getComptes(){
List<Compte> cptes=new
ArrayList<Compte>();
[Link] (new Compte (1,7000)); [Link] (new Compte
(2,9000)); return cptes;
}}
med@[Link]
JAX-WS / JAXB
JAX-WS s'appuie sur l'API JAXB 2.0 pour tout ce qui
concerne la correspondance entre document XML et
objets Java.
JAXB 2.0 permet de mapper des objets Java dans un
document XML et vice versa.
Il permet aussi de générer des classes Java à partir un
schéma XML et vice et versa.
Principe de JAXB
Le mapping d'un document XML à des objets (unmarshal)
med@[Link]
Comment développer un web service
JAW-WS
1. Créer le service Web
◦ Développer le web service
◦ Déployer le web service
Un serveur HTTP
Un Conteneur WS ( JaxWS, AXIS, CXF, etc…)
2. Tester le web service avec un analyseur
SOAP
◦ SoapUI,
◦ Oxygen, etc…
3. Créer les clients :
◦ Un client Java
◦ Un client .Net
◦ Un client PHP
med@[Link]
Application
Créer un web service java en
utilisant JaxWS qui permet de :
◦ Convertir un montant de l’auro en DH
◦ Consulter un compte sachant son code
◦ Consulter une liste de comptes
Tester le web service avec un
analyseur SOAP
Créer un client Java
Créer un client .Net
Créer un client PHP
med@[Link]
Architectur
e1 Serveur JAXWS
Client SOAP (Java, .Net, PHP) BanqueService
+conversion(double mt):double
+Compte getCompte()
Client +List<Compte> getComptes()
3 4
1 6
2
STUB Compte
SOA
SKELETO -code : int
P N -solde: double
5
1
Le client demande au stub de faire appel à la méthode conversion(12)
2
Le Stub se connecte au Skeleton et lui envoie une requête SOAP
3
Le Skeleton fait appel à la méthode du web service
4
Le web service retourne le résultat au Skeleton
5
Le Skeleton envoie le résultat dans une la réponse SOAP au Stub
6
Le Stub fournie lé résultat au client med@[Link]
Développer le web service avec
JAX-WS
Outils à installer :
◦ JDK1.7
◦ Editeur java : Eclipse.
Créerun projet java en utilisant JDK1.7 comme
compilateur et environnement d’exécution java.
◦ Structure du projet :
med@[Link]
Implémentation de la classe
Compte
package metier;
import
[Link];
import
[Link];
import
[Link];
@XmlRootElement
@XmlAccessorType([Link])
public class Compte {
private Long code;
private double solde; @XmlTransient
private Date dateCreation;
// Constructeur sans paramètre et avec paramètre
// Getters et setters
}
Implémentation du web service
package ws;
import [Link].*;
import [Link].*;
import
[Link];
@WebService(serviceName="BanqueWS")
public class BanqueService {
@WebMethod(operationName="ConversionEuroToDh")
public double conversion(@WebParam(name="montant")double
mt){ return mt*11;
}
@WebMethod
public Compte getCompte(@WebParam(name="code")Long code)
{ return new Compte (code,7000,new Date());
}
@WebMethod
public List<Compte> getComptes(){
List<Compte> cptes=new
ArrayList<Compte>();
[Link] (new Compte (1L,7000,new
Date())); [Link] (new Compte
(2L,7000,new Date())); return cptes;
}}
med@[Link]
Simple Serveur JAX WS
import
[Link];
import [Link];
public class ServeurJWS {
public static void main(String[] args) {
String url="[Link]
[Link](url, new
BanqueService());
[Link](url);
}
}
med@youssfi.
Analyser le WSDL
Pour Visualiser le WSDL, vous pouvez
utiliser un navigateur web
med@[Link]
Structure du WSDL
Un document WSDL se compose d'un ensemble d'éléments
décrivant les types de données utilisés par le service, les
messages que le service peut recevoir, ainsi que les liaisons
SOAP associées à chaque message.
Le schéma suivant illustre la structure du langage WSDL qui
est un document XML, en décrivant les relations entre les
sections constituant un document WSDL.
med@[Link]
Structure du WSDL
Un fichier WSDL contient donc sept éléments.
◦ Types : fournit la définition de types de
données utilisés pour décrire les messages
échangés.
◦ Messages : représente une définition
abstraire (noms et types) des données en
cours de transmission.
◦ PortTypes : décrit un ensemble
d'opérations. Chaque opération a zéro ou
un message en entrée, zéro ou plusieurs
messages de sortie ou d'erreurs.
◦ Binding : spécifie une liaison entre un
<portType> et un protocole concret (SOAP,
HTTP...).
◦ Service : indique les adresses de port de chaque
liaison.
◦ Port : représente un point d'accès de
services défini par une adresse réseau et une
liaison.
◦ Opération : c'est la description d'une
action exposée dans le port.
med@[Link]
Structure du WSDL
med@[Link]
Elément Types
med@[Link]
XML Schema
med@youssfi.
XML Schema
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:tns="[Link] xmlns:xs="[Link]
version="1.0" targetNamespace="[Link]
<xs:element name="ConversionEuroToDh"
type="tns:ConversionEuroToDh"></xs:element>
<xs:element name="ConversionEuroToDhResponse"
type="tns:ConversionEuroToDhResponse"/>
<xs:element name="compte" type="tns:compte"></xs:element>
<xs:element name="getCompte" type="tns:getCompte"></xs:element>
<xs:element name="getCompteResponse"
type="tns:getCompteResponse"></xs:element>
<xs:element name="getComptes" type="tns:getComptes"></xs:element>
<xs:element name="getComptesResponse"
type="tns:getComptesResponse"></xs:element>
<xs:complexType name="ConversionEuroToDh">
<xs:sequence>
<xs:element name="montant" type="xs:double"></xs:element>
</xs:sequence>
</
xs:complexType>
<xs:complexType name="ConversionEuroToDhResponse">
<xs:sequence>
<xs:element name="return" type="xs:double"></xs:element>
</xs:sequence>
</
xs:complexType>
XML Schema
<xs:complexType name="getCompte">
<xs:sequence>
<xs:element name="code" type="xs:long" minOccurs="0"></xs:element>
</xs:sequence>
</
xs:complexType>
<xs:complexType name="getCompteResponse">
<xs:sequence>
<xs:element name="return" type="tns:compte" minOccurs="0"></xs:element>
</xs:sequence>
</
xs:complexType>
<xs:complexType name="compte">
<xs:sequence>
<xs:element name="code" type="xs:long" minOccurs="0"></xs:element>
<xs:element name="solde" type="xs:double"></xs:element>
</xs:sequence>
</
xs:complexType>
<xs:complexType name="getComptes">
<xs:sequence></xs:sequence>
</xs:complexType>
<xs:complexType name="getComptesResponse">
<xs:sequence>
<xs:element name="return" type="tns:compte" minOccurs="0"
maxOccurs="unbounded"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
Elément message
<message name="getCompte">
<part name="parameters"
element="tns:getCompte"></part>
</message>
<message name="getCompteResponse">
<part name="parameters"
element="tns:getCompteResponse"></part>
</message>
med@[Link]
Elément portType
<portType
name="BanqueService">
<operation
name="getCompte">
<input wsam:Action="[Link]
message="tns:getCompte"></input>
<output wsam:Action="[Link]
message="tns:getCompteResponse"></output>
</operation>
<operation name="getComptes">
<input wsam:Action="[Link]
message="tns:getComptes"></input>
<output wsam:Action="[Link]
message="tns:getComptesResponse"></output>
</operation>
<operation name="ConversionEuroToDh">
…..
</operation>
</portType> med@youssfi.
Elément binding
<service name="BanqueWS">
<port name="BanqueServicePort"
binding="tns:BanqueServicePortBinding">
<soap:address location="[Link]
</port>
</service>
med@[Link]
Tester les méthodes du web
service avec un analyseur
SOAP : SoapUI
med@[Link]
Tester les méthodes du web
service avec un analyseur
SOAP : SoapUI
med@[Link]
Tester la méthode
conversion
Requête SOAP
<soapenv:Envelope
xmlns:soapenv="[Link]
xmlns:ws="[Link]
<soapenv:Header/>
<soapenv:Body>
<ws:ConversionEuroToDh>
<montant>60</montant>
</ws:ConversionEuroToDh>
</soapenv:Body>
</soapenv:Envelope>
Réponse SOAP
<S:Envelope xmlns:S="[Link]
<S:Body>
<ns2:ConversionEuroToDhResponse xmlns:ns2="[Link]
<return>660.0</return>
</ns2:ConversionEuroToDhResponse>
</S:Body>
</S:Envelope>
med@[Link]
Tester la méthode getCompte
Requête SOAP
<soapenv:Envelope
xmlns:soapenv="[Link]
xmlns:ws="[Link]
<soapenv:Header/>
<soapenv:Body>
<ws:getCompte>
<code>2</code>
</ws:getCompte>
</soapenv:Body>
</soapenv:Envelope>
Réponse SOAP
<S:Envelope xmlns:S="[Link]
<S:Body>
<ns2:getCompteResponse xmlns:ns2="[Link]
<return>
<code>2</code>
<solde>7000.0</solde>
</return>
</ns2:getCompteResponse>
</S:Body>
</S:Envelope>
med@[Link]
Tester la méthode getComptes
Requête SOAP
<soapenv:Envelope
xmlns:soapenv="[Link]
xmlns:ws="[Link]
<soapenv:Header/>
<soapenv:Body>
<ws:getComptes/>
</soapenv:Body>
</soapenv:Envelope>
Réponse SOAP
<S:Envelope xmlns:S="[Link]
<S:Body>
<ns2:getComptesResponse xmlns:ns2="[Link]
<return>
<code>1</code>
<solde>7000.0</solde>
</return>
<return>
<code>2</code>
<solde>7000.0</solde>
</return>
</ns2:getComptesResponse>
</S:Body>
</S:Envelope> med@youssfi.
Client Java
Créer un nouveau projet Java
Générer un proxy
◦ SoapUI est l’un des outils qui peuvent
être utilisés pour générer les artefacts
client en utilisant différents Framework
(Axis, CXF, JaxWS, etc…)
◦ Le JDK fournit une commande simple qui
permet de générer un STUB JaxWS pour
l’accès à un web service. Cette commande
s’appelle wsimport.
◦ SoapUI a besoin de savoir le chemin
de cette commande
◦ Avec la commande File
>Preferences>Tools , vous pouvez
configurer le ce chemin comme le montre
la figure suivante :
med@[Link]
Préférence générale de
SoapUI
med@youssfi.
Générer le STUB JaxWS
med@[Link]
Fichiers Générés
med@[Link]
Client Java
import [Link];
Serveur
import
[Link];
import [Link]; Web
Service
import [Link];
public class ClientWS {
Skeleton
public static void main(String[] args) {
BanqueService stub=new
BanqueWS().getBanqueServicePort(); SOAP
[Link]("Conversion");
[Link]([Link](9000)); Stub
[Link]("Consulter un compte");
Compte cp=[Link](2L); Client
[Link]("Solde="+[Link]())
; [Link]("Liste des comptes");
Java
List<Compte> cptes=[Link]();
for(Compte c:cptes){
[Link]([Link]()+"- -"+[Link]());
}
}
}
Architecture
Client
SOAP Serveur
JAXWS
BanqueService
Client +conversion(double mt):double
+test():String
1 6 3 4
2
STUB SKELETO
SOA
N
P
5
1 Le client demande au stub de faire appel à la méthode conversion(12)
2 Le Stub se connecte au Skeleton et lui envoie une requête SOAP
BanqueService
Web Container +conversion(double mt):double
:Tomcat +getCompte(int code):Compte
+getComptes():List<Compte>
3 4
2
[Link]
SOA SKELETON
P5
1 HTTP 6
Client HTTP
med@[Link]
Création d’un projet Web Dynamique basé sur
Tomcat 7
Créer
un projet Web Dynamique basé sur
Tomcat 7
med@[Link]
Projet Web Dynamique
med@[Link]
Générer un proxy (Stub) pour le web
Service
Fichier > Nouveau > Web Service
Client
med@[Link]
Génération du proxy
Générer le proxy à partir du WSDL
med@[Link]
Fichier Générés
Le proxy généré est basé sur AXIS
med@[Link]
Client JSP
<%@page import="[Link]"%>
<%
double montant=0; double resultat=0;
if([Link]("montant")!=null){
montant=[Link]([Link]("montan
t")); BanqueServiceProxy service=new
BanqueServiceProxy();
resultat=[Link](montant);
}
%>
<html><body>
<form action="[Link]">
Montant :<input type="text" name="montant" value="<%=montant%>">
<input type="submit" value="OK">
</form>
<%=montant %> en Euro est égale à <%=resultat %> en DH
</body></html>
med@[Link]
Client SOAP avec .Net
En utilisant Visual Studio (2010),
Créer un projet C# de type
Console
med@[Link]
Générer Le Proxy client Soap
med@[Link]
Code C# du client Serveur
using System;
namespace ClientSOAP
{ Web
Service
class Program
{
static void Main(string[] args) Skeleton
{
[Link] stub =
SOAP
new
[Link]();
Stub
[Link]("-------- Conversion----------");
[Link]([Link](34));
Client .N
[Link]("-------- Consulter un Compte
--------------------------------------------------------------------------------------------- ")
; et
[Link] cp = [Link](2L);
[Link]("Solde=" + [Link]);
[Link]("-------- Liste des comptes
------------------------------------------------------------------------------------------ ")
;
[Link][] cptes =
[Link](); for (int i = 0; i < [Link];
i++)
{
med@[Link]
Client Graphique .Net
Créer un nouveau Projet Visual
Studio de type Windows Forms
Application
med@[Link]
Générer à nouveau le proxy
SOAP
med@[Link]
Dessiner les composants
graphique de l’interface
Serveur
Web Service
Skeleton
SOAP
Stub
Client .Net
med@[Link]
Code C#
using System;using [Link]; using [Link];using
[Link]; using [Link];using [Link]; using [Link];using
[Link]; namespace ClientGraphiqueSOAP { Serveur
public partial class Form1 : Form {
private [Link]
Web
stub; public Form1() { Service
InitializeComponent();stub = new [Link]();
Skeleton
}
private void button1_Click(object sender, EventArgs e)
SOAP
{ double mt = [Link]([Link]);
double res = [Link](mt); Stub
[Link] = [Link]();
}
private void button2_Click(object sender, EventArgs Client .Net
e) { [Link][] cptes =
[Link]();
DataTable dt = new DataTable("comptes");
[Link]("CODE");
[Link]("SOLDE");
for (int i = 0; i < [Link]; i++) {
[Link](cptes[i].code,
cptes[i].solde);
}
[Link] = dt;
} }}
med@[Link]
Web Service Java et Client PHP
Serveur JAXWS
BanqueService
Serveur Web +conversion(double mt):double
Apache +getCompte(int code):Compte
+getComptes():List<Compte>
3 4
2
[Link]
SOA SKELETON
P5
1 HTTP 6
Client HTTP
med@[Link]
Exemple de Client SOAP PHP
<?php
$client = new SoapClient('[Link]
$param=new stdClass();
$param->montant=23;
$res=$client-> soapCall("conversionEuroDH",array($param));
//var_dump($res);
echo($res-
>return);
$param2=new stdClass();
$param2->arg0=2;
$res2=$client-> soapCall("getCompte",array($param2));
//var_dump($res2); echo("Code=".
$res2->return->code);
echo("<br/>Solde=".$res2->return->solde);
$res3=$client-> soapCall("getComptes",array());
//
var_dump($res3);
echo ("<hr/>");
foreach($res3->return as
$cpte){ echo("Code=".$cpte-
>code);
echo("<br/>Solde=".$cpte->solde);
echo("<br/>");
}
?>
med@[Link]
Configuration du plugin Eclipse PDT
Après avoir installé Easy PHP ou Wamp Server (Apage, MySQL, PHP,
PhpMyAdmin)
Window > preferences
med@[Link]
Projet PHP
med@[Link]
Projet PHP
med@[Link]
Nouvelle page PHP
med@[Link]
Code PHP
<?php
$montant=0;$resultat=0;
if (isset($_GET['montant'])){
$montant=$_GET['montant'];
$client = new SoapClient('[Link]
$param=new stdClass();
$param->montant=$montant;
$rep=$client-> soapCall("conversionEuroDH",array($param));
$resultat=$rep->return;
}
?>
<html>
<body>
<form action="[Link]">
Montant :<input type="text" name="montant" value="<?php
echo($montant)?>">
<input type="submit" value="OK">
</form>
<?php echo($montant)?> en Euro est égale à <?php echo($resultat)?> en DH
</body>
</html> med@[Link]
Un autre
exemple Client
SOAP PHP
<?php
$mt=0;
if(isset($_POST['action'])){
$action=$_POST['action'];
if($action=="OK"){
$mt=$_POST['montant'];
$client=new SoapClient("[Link]
$param=new stdClass();
$param->montant=$mt;
$rep=$client-> soapCall("conversionEuroToDh",array($param));
$res=$rep->return;
}
elseif($action=="listComptes"){
$client=new SoapClient("[Link]
$res2=$client soapCall("getComptes",array());
->
}
}
?>
med@[Link]
Suite de l’exemple du Client SOAP PHP
<html>
<body>
<form method="post" action="[Link]">
Montant:<input type="text" name="montant" value="<?php echo($mt)?>">
<input type="submit" value="OK" name="action">
<input type="submit" value="listComptes" name="action">
</form>
Rsultat:
<?php if (isset($res)){
echo($res);
}
?>
<?php if(isset($res2)){?>
<table border="1" width="80%">
<tr>
<th>CODE</th><th>SOLDE</th>
</tr>
<?php foreach($res2->return as $cp) {?>
<tr>
<td><?php echo($cp->code)?></td>
<td><?php echo($cp->solde)?></td>
</tr>
<?php }?>
</table>
<?php }?>
</body>
</html>
med@[Link]
Web Service dans une
application web J2EE basée
sur Spring
On souhaite créer une application web J2EE
basée sur Spring qui permet de déployer un web
service qui permet de :
◦ Ajouter un compte
◦ Consulter un compte
◦ Consulter tous les comptes
◦ Effectuer un versement d’un montant dans un compte
◦ Effectuer un retrait d’un montant sur un compte
◦ Effectuer un virement d’un montant d’un compte vers un
autre
◦ Supprimer un compte
Chaque compte est défini par le code, le solde
et la date création
Les comptes seront stockés dans une base de
données MySQL
med@[Link]
Architectu SGBD
re
Web
Container Spring IOC
Container
dependenc
ies
ContextLoaderListner
Spring
SimpleJaxW JPATransaction EntityManag Jax
s Manager er WS
ServiceExport
er
FactoryBean
Jax RS
[Link] Couche Jacks
Métier Couche
Couche on
DAO
SOAP
IBanqMetier [Link]
BanqControll
er
IBanqueDAO
BanqueService
JPA
BanqMetierImpl
BanqDAOImpl Hiberna
DispatcherServ
let te JDBC
HTTP SOAP
HTML
Client
Client SOAP
HTTP
Installation du plugin :
spring tools pour eclipse
med@[Link]
Installation du plugin :
spring tools pour eclipse
med@[Link]
Création d’un projet
Spring
med@[Link]
Création d’un projet Spring
med@[Link]
[Link]
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link]
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/[Link]</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-
class>[Link]</lis
tener- class>
</listener>
med@[Link]
[Link]
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>[Link]
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/[Link]
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
med@[Link]
>/WEB-INF/spring/[Link]
• Ce fichier est lu par ContextLoaderListener, au démarrage du
serveur .
• C’est un fichier dans lequel contexte de l’application sera construit
• ContextLoaderListener représente Spring IOC
• c’est donc un fichier pour l’injection des dépendances
• Pour le moment, il est vide
[Link] [Link]
med@[Link]
Fonctionnement
Clien Tomcat
t
Lire [Link]
:ContextLoaderListne :DispatcherServlet
r
:HomeController
Instancier Lire
Lire
root-
Req [Link]
[Link]
HTTP Instancier
GET/
doGet(request,respo :[Link]
nse) instanci
er
home()
HTTP
M
od
el
A
nd
Vi
Rep e
w
instanci rendu
er
html
med@[Link]
Structure du projet
med@[Link]
Création des entités
package [Link];
import
[Link];
import [Link];
import [Link];
@XmlRootElement
public class Compte implements Serializable {
private Long code;
private double solde;
private Date
dateCreation;
// Getters et Setters
// Constructeurs
}
med@[Link]
Web Service
package [Link];
import
[Link].*;
import
[Link].*;
@WebService
public class BanqueService {
@WebMethod(operationName="conversionEuroToDH"
) public double conversion(double mt){
return mt*11;
}
@WebMethod
public Compte getCompte(@WebParam(name="code")Long code){
return new Compte(code,[Link]()*4000, new
Date());
}
@WebMethod
public List<Compte> getComptes(){
List<Compte> cptes=new
ArrayList<Compte>();
[Link] (new Compte(1L,[Link]()*4000, new
Date())); [Link] (new Compte(2L,[Link]()*4000,
new Date())); return cptes;
}
}
Déploiement du web service avec Spring
/WEB-INF/spring/[Link]
med@[Link]
Déploiement du projet
Déployer le projet en utilisant
Tomcat7
Démarrer le serveur Tomcat
med@[Link]
Tester le web service
med@youssfi.
Persistance des comptes avec JPA
Hibernate
med@[Link]
Maven Dependencies
<!-- Hibernate-->
<dependency>
<groupId>[Link]</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>[Link]</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>hibernate-validator</artifactId>
<version>[Link]</version>
</dependency>
<!-- MySQL Connector-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
med@[Link]
Persistance de la classe
Compte
package [Link];
import [Link].*;
import [Link].*;
import [Link].*;
import [Link];
@XmlRootElement
@Entity
public class Compte implements
Serializable { @Id
@GeneratedValue(strategy=[Link]
Y) private Long code;
private double solde;
private Date
dateCreation;
// Getters et Setters
// Constructeurs
}
med@[Link]
src/main/resources/META-INF/[Link]
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
[Link] ">
<persistence-unit name="UP_EBOUTIQUE" transaction-type="RESOURCE_LOCAL">
<provider>[Link]</provider>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="[Link]" value="update"/>
<property name="[Link]"
value="[Link]
t"/>
</properties>
</persistence-unit>
</persistence>
med@[Link]
Configuration JPA avec Spring
IOC
med@[Link]
Maven Properties
<properties>
<java-version>1.6</java-version>
<[Link]-
version>[Link]</[Link]-
version>
<[Link]-version>1.6.10</[Link]-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
</properties>
med@[Link]
Maven Dependencies
<!-- Spring -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-context</artifactId>
<version>${[Link]-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${[Link]-version}</version>
</dependency>
med@[Link]
Maven Dependencies
<!-- Spring -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-tx</artifactId>
<version>${[Link]-version}</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-orm</artifactId>
<version>${[Link]-version}</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-beans</artifactId>
<version>${[Link]-version}</version>
</dependency>
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-core</artifactId>
<version>${[Link]-version}</version>
</dependency>
med@[Link]
Configuration JPA avec Spring
IOC :
/EBoutiqueV2/src/main/resources/
[Link]
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="[Link]
xmlns:xsi="[Link]
xmlns:context="[Link]
ext" xmlns:tx="[Link]
xsi:schemaLocation="[Link] [Link]
[Link] [Link]
[Link] [Link]
<bean id="datasource"
class="[Link]
e">
<property name="driverClassName" value="[Link]"></property>
<property name="url" value="jdbc:mysql://localhost:3306/eBanque"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>
Configuration JPA avec Spring
IOC :
/EBoutiqueV2/src/main/resources/
[Link]
<bean id="persistenceUnitManager"
class="[Link]">
<property name="defaultDataSource" ref="datasource"></property>
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/[Link]</value>
</list>
</property>
</bean>
<bean id="entityManagerFactory"
class="[Link]">
<property name="persistenceUnitManager" ref="persistenceUnitManager"></property>
<property name="persistenceUnitName" value="UP_EBOUTIQUE"></property>
</bean>
<bean id="transactionManager"
class="[Link]">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:annotation-config></context:annotation-config>
</beans>
Tester la persistance des
entités
Créer la base de données
eBanque
Redéployer le projet
La table compte devrait être
générée
med@[Link]
Couche DAO
med@[Link]
Interface IBanqueDAO
package [Link];
import [Link];
import [Link];
public interface IBanqueDAO {
public void addCompte(Compte c);
public List<Compte>
listComptes(); public Compte
getCompte(Long code);
public void verser(Long code,double mt);
public void retirer(Long code, double
mt);
public void virement(Long cpte1,Long cpte2,double
mt); public void deleteCompte(Long code);
}
med@[Link]
Implémentation DAO : ORM avec JPA
package [Link];
import [Link].*; import [Link].*;
import [Link];
public class BanqueDAOImpl implements IBanqueDAO
{ @PersistenceContext
private EntityManager em;
@Override
public void addCompte(Compte c) {
[Link](c); } @Override
public List<Compte> listComptes() {
Query req=[Link]("select c from Compte
c"); return [Link]();
}
@Override
public Compte getCompte(Long code) {
Compte cp=[Link]([Link],
code);
if(cp==null) throw new RuntimeException("Compte
Introuvable"); return cp;
}
med@[Link]
Implémentation DAO : ORM avec JPA
@Overrid
e
public void verser(Long code, double mt) {
Compte cp=getCompte(code); [Link]([Link]()+mt);
}
@Override
public void retirer(Long code, double mt) {
Compte cp=getCompte(code);
if(mt>[Link]()) throw new RuntimeException("Solde
Insuffisant"); [Link]([Link]()-mt);
}
@Override
public void virement(Long cpte1, Long cpte2, double mt) {
retirer(cpte1, mt); verser(cpte2, mt);
}
@Override
public void deleteCompte(Long code) {
Compte cp=getCompte(code);
[Link](cp);
}
}
med@[Link]
Couche Métier
med@[Link]
Interface
IBanqueMetier
package [Link];
import [Link];
import
[Link];
public interface IBanqueMetier {
public void addCompte(Compte c);
public List<Compte> listComptes();
public Compte getCompte(Long code);
public void verser(Long code,double mt);
public void retirer(Long code, double
mt);
public void virement(Long cpte1,Long cpte2,double
mt); public void deleteCompte(Long code);
}
med@[Link]
Implémentation Métier
package [Link];import [Link];
import [Link];
import [Link]; import
[Link]; @Transactional
public class BanqueMetierImpl implements
IBanqueMetier { private IBanqueDAO dao;
public void setDao(IBanqueDAO dao) { [Link] = dao; }
@Override
public void addCompte(Compte c) { [Link](c);}
@Override
public List<Compte> listComptes() { return
[Link](); } @Override
public Compte getCompte(Long code) { return [Link](code); }
med@[Link]
Implémentation Métier (suite)
@Overrid
e
public void verser(Long code, double mt) { [Link](code, mt); }
@Override
public void retirer(Long code, double mt) { [Link](code,
mt);
}
@Override
public void virement(Long cpte1, Long cpte2, double
mt) { [Link](cpte1, cpte2, mt);
}
@Override
public void deleteCompte(Long code) {
[Link](code);
}
}
med@[Link]
Web Service
package [Link]; import [Link].*; import
[Link].*; import [Link];
import [Link];
@WebService
public class BanqueService {
private IBanqueMetier
metier;
@WebMethod(exclude=true)
public void setMetier(IBanqueMetier metier) {[Link] = metier;
} @WebMethod
@Oneway
public void addCompte(@WebParam(name="solde")double solde){
[Link](new Compte(null, solde,new Date()));
}
@WebMethod
public Compte getCompte(@WebParam(name="code")Long
code){ return [Link](code);
}
@WebMethod
public List<Compte> getComptes(){ return [Link](); }
Web Service
@WebMethod
public void verser(
@WebParam(name="code")Long code,
@WebParam(name="montant")double mt){ [Link](code,
mt); } @WebMethod
public void retirer(
@WebParam(name="code")Long code,
@WebParam(name="montant")double mt){ [Link](code, mt); }
@WebMethod
public void virement(
@WebParam(name="cpte1")Long cpte1,
@WebParam(name="cpte2")Long cpte2,
@WebParam(name="montant")double mt){ [Link](cpte1,
cpte2, mt); }
@WebMethod
public void supprimerCompte(@WebParam(name="code")Long code){
[Link](code);
} }
Injection des
dépendances
med@[Link]
Injection des dépendance :root-
[Link]
<!-- Root Context: defines shared resources visible to all other web
components -->
<bean id="dao" class="[Link]"></bean>
<bean id="metier" class="[Link]">
<property name="dao" ref="dao"></property>
</bean>
<bean id="service" class="[Link]">
<property name="metier" ref="metier"></property>
</bean>
<bean
class="[Link]">
<property name="baseAddress"
value="[Link]
</bean>
med@[Link]
Injection des dépendance :root-
[Link]
<bean id="datasource" class="[Link]">
<property name="driverClassName" value="[Link]"></property>
<property name="url" value="jdbc:mysql://localhost:3306/eBanque"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>
<bean id="persistenceUnitManager"
class="[Link]
ager">
<property name="defaultDataSource" ref="datasource"></property>
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/[Link]</value>
</list>
</property>
</bean>
<bean id="entityManagerFactory"
class="[Link]">
<property name="persistenceUnitManager" ref="persistenceUnitManager"></property>
<property name="persistenceUnitName" value="UP_BANQUE"></property>
</bean>
<bean id="transactionManager" class="[Link]">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:annotation-config></context:annotation-config>
med@[Link]
Tester les méthodes avec un
analyseur SOAP :SoapUI
SGBD
Couche DAO
Couche Métier
Web Service
SOAP
SoapUI
med@[Link]
Tester les méthodes
Requête SOAP pour ajouter un compte
<soapenv:Envelope
xmlns:soapenv="[Link]
xmlns:ser="[Link]
<soapenv:Header/>
<soapenv:Body>
<ser:addCompte>
<solde>20000</solde>
</ser:addCompte>
</soapenv:Body>
</soapenv:Envelope>
Pas de réponse SOAP (@oneway )
med@[Link]
Tester les méthodes
Requête SOAP pour consulter un compte
<soapenv:Envelope
xmlns:soapenv="[Link]
" xmlns:ser="[Link]
<soapenv:Header/>
<soapenv:Body>
<ser:getCompte>
<code>1</code>
</ser:getCompte>
</soapenv:Body>
</soapenv:Envelope>
Réponse SOAP
<S:Envelope xmlns:S="[Link]
<S:Body>
<ns2:getCompteResponse
xmlns:ns2="[Link]
<return>
<code>1</code>
<dateCreation>2014-01-24T[Link]Z</dateCreation>
<solde>92600.0</solde>
</return>
</ns2:getCompteResponse>
</S:Body>
</S:Envelope>
med@[Link]
Tester les méthodes
Requête SOAP pour consulter les comptes
<soapenv:Envelope
xmlns:soapenv="[Link]
xmlns:ser="[Link]
<soapenv:Header/>
<soapenv:Body>
<ser:getComptes/>
</soapenv:Body>
</soapenv:Envelope>
Réponse SOAP
<S:Envelope xmlns:S="[Link]
<S:Body>
<ns2:getComptesResponse xmlns:ns2="[Link]
<return>
<code>1</code>
<dateCreation>2014-01-24T[Link]Z</dateCreation>
<solde>92600.0</solde>
</return>
<return>
<code>2</code>
<dateCreation>2014-01-25T[Link]Z</dateCreation>
<solde>20000.0</solde>
</return>
</ns2:getComptesResponse>
</S:Body>
</S:Envelope>
med@[Link]
Tester les méthodes
Requête SOAP pour verser un montant
<soapenv:Envelope
xmlns:soapenv="[Link]
xmlns:ser="[Link]
<soapenv:Header/>
<soapenv:Body>
<ser:verser>
<code>1</code>
<montant>2000</montant>
</ser:verser>
</soapenv:Body>
</soapenv:Envelope>
Réponse SOAP
<S:Envelope
xmlns:S="[Link]
<S:Body>
<ns2:verserResponse
xmlns:ns2="[Link]
</S:Body>
</S:Envelope>
med@[Link]
Retirer un montant
Requête SOAP pour verser un montant
<soapenv:Envelope
xmlns:soapenv="[Link]
xmlns:ser="[Link]
<soapenv:Header/>
<soapenv:Body>
<ser:retirer>
<code>1</code>
<montant>7000000</montant>
</ser:retirer>
</soapenv:Baody>
</soapenv:Envelope>
Réponse SOAP
<S:Envelope xmlns:S="[Link]
<S:Body>
<S:Fault xmlns:ns4="[Link]
envelope">
<faultcode>S:Server</faultcode>
<faultstring>Solde Insuffisant</faultstring>
</S:Fault>
</S:Body>
</S:Envelope>
med@[Link]
Effectuter un virement
Requête SOAP pour effectuer un virement
<soapenv:Envelope
xmlns:soapenv="[Link]
xmlns:ser="[Link]
<soapenv:Header/>
<soapenv:Body>
<ser:virement>
<cpte1>1</cpte1>
<cpte2>2</cpte2>
<montant>8000</montant>
</ser:virement>
</soapenv:Body>
</soapenv:Envelope>
Réponse SOAP
<S:Envelope
xmlns:S="[Link]
<S:Body>
<ns2:virementResponse
xmlns:ns2="[Link]
</S:Body>
</S:Envelope>
med@[Link]
Supprimer un compte
Requête SOAP pour supprimer un compte
<soapenv:Envelope
xmlns:soapenv="[Link]
xmlns:ser="[Link]
<soapenv:Header/>
<soapenv:Body>
<ser:supprimerCompte>
<code>2</code>
</ser:supprimerCompte>
</soapenv:Body>
</soapenv:Envelope>
Réponse SOAP
<S:Envelope xmlns:S="[Link]
<S:Body>
<ns2:supprimerCompteResponse
xmlns:ns2="[Link]
</S:Body>
</S:Envelope>
med@[Link]
Web services dans une
application web J2EE basée sur
EJB3 et JBoss7.1
Dans une application web J2EE basée sur
un serveur d’application J2EE
◦ Web Sphere
◦ Jboss
◦ Jonas
◦ Glassfish
Aucune configuration n’est nécessaire pour
déployer le web service
Il suffit de créer un projet web basé sur le
serveur d’application
Créer le web service
Démarrer le serveur et déployer le projet web
Chaque serveur d’application possède
sa propre implémentation JAX WS :
CXF, AXIS, etc…
med@[Link]
Application
Créer une application qui permet de gérer des
comptes via un service web.
Chaque compte est défini par un code, un solde, la date
de création
Les comptes sont stockés dans une base de données
MYSQL.
Le mapping objet relationnel est effectué via JPA
(EJB Entity et Session )
La couche service est représenté par un web
service de type JAXRS.
L’application doit permettre de :
◦ Ajouter un compte
◦ Consulter tous les compte
◦ Consulter un compte sachant son code
◦ Effectuer un versement d’un montant dans un compte
◦ Effectuer un retrait d’un montant sur un compte
L’application web sera déployé dans un serveur JBoss7
Créer un client java et un client PHP.
med@[Link]
Architecture
Seveur d’application J2EE : JBOSS (http :8080)
SOAP
SOAP Apache :8888
Oxygen HTTP
med@[Link]
Structure du projet J2EE
Configuration de l’unité de
Persistance JPA
EJB Session
EJB Entity
Interface Local de
med@[Link]
Données manipulées : Entity Compte
package metier;
import [Link]; import [Link]; import
[Link].*; @Entity
@Table(name="COMPTES")
public class Compte implements Serializable
{ @Id
@GeneratedValue(strategy=[Link]
TITY)
private Long code;
private double
solde;
private Date dateCreation;
public Compte() {
}
public Compte(double solde) {
[Link] = solde;
[Link]=new
Date();
}
// Getters et Setters
}
med@[Link]
Interface Locale
package metier;
import
[Link];
import [Link];
@Local
public interface IBanqueLocal {
public Compte addCompte(Compte
c); public List<Compte>
getAllComptes();
public void verser(Long code,double montant);
public void retirer(Long code,double montant);
public Compte consulterCompte(Long code);
}
med@[Link]
Implémentation EJB Session sans état
package metier;
import
[Link];
import
[Link];
import
[Link].*;
@Stateless(name="BP")
public class BanqueEJBImpl implements IBanqueLocal {
@PersistenceContext(unitName="UP_BP")
EntityManager em;
@Override
public Compte addCompte(Compte c) {
[Link](c);
return c;
}
@Override
public List<Compte> getAllComptes() {
Query req=[Link]("select c from Compte c");
return [Link]();
}
med@[Link]
Implémentation EJB Session sans état
@Override
public void verser(Long code, double
montant) { if(montant<=0) throw new
RuntimeException ("Le Montant doit être
supérieur à zero"); Compte
c=[Link]([Link], code);
[Link]([Link]()+montant);
[Link](c);
}
@Override
public void retirer(Long code, double montant) {
if(montant<=0) throw new RuntimeException
("Le Montant doit être supérieur à zero");
Compte c=[Link]([Link], code);
if([Link]()<=montant) throw new RuntimeException
("Solde Insuffisant");
[Link]([Link]()-montant);
}
med@[Link]
Implémentation EJB Session sans état
@Override
public Compte consulterCompte(Long code) {
Compte c=[Link]([Link], code);
if(c==null) throw new RuntimeException
("Compte introuvable");
return c;
}
}
med@[Link]
Configuration de l’unité
de persistance :
[Link]
<?xml version="1.0" encoding="UTF-8"?>
<persistence
xmlns="[Link]
xmlns:xsi="[Link]
xsi:schemaLocation="[Link]
ence
[Link]
.xsd" version="1.0">
<persistence-unit name="UP_BP">
<jta-data-source>java:/dsBP</jta-data-source>
<properties>
<property name="[Link]" value="update"/>
</properties>
</persistence-unit>
</persistence>
med@[Link]
Data source
Fichier [Link] de JBoss
<datasources>
<datasource jndi-name="java:/dsBP" pool-name="dsBP"
enabled="true" >
<connection-url>jdbc:mysql://[Link]:3306/DB_BP</connection-
url>
<driver-class>[Link]</driver-class>
<driver>mysql</driver>
<security>
<user-name>root</user-name>
<password></password>
</security>
</datasource>
<drivers>
<driver name="mysql" module="[Link]"/>
</drivers>
</datasources>
med@[Link]
Web Service
package service;
import
[Link];
import [Link];import [Link].*;
import [Link];import [Link];
@WebService
public class BanqueService {
@EJB
private IBanqueLocal metier;
@WebMethod
public Compte addCompte(@WebParam(name="solde")double
solde) { return [Link](new Compte(solde));
}
@WebMethod
public List<Compte> getAllComptes()
{ return [Link]();
}
med@[Link]
Web Service
@WebMethod
public void verser(@WebParam(name="code")Long code,
@WebParam(name="montant")double montant) {
[Link](code, montant);
}
@WebMethod
public void retirer(@WebParam(name="code")Long
code, @WebParam(name="montant")double montant) {
[Link](code, montant);
}
@WebMethod
public Compte consulterCompte(@WebParam(name="code")Long
code) { return [Link](code);
}
}
med@[Link]
Déployer et Tester le projet
Web
Démarrer le serveur JBoss
Déployer le projet Web
Consulter le WSDL
Tester Le web service avec Oxygen
med@[Link]
Analyse du WSDL
med@[Link]
Resumé du WSDL
med@[Link]
Le schéma XML des données
échangées :
<wsdl:types>
<xs:schema elementFormDefault="unqualified" targetNamespace="[Link]
version="1.0" xmlns:tns="[Link]
xmlns:xs="[Link]
<xs:element name="addCompte" type="tns:addCompte"/>
<xs:element name="addCompteResponse" type="tns:addCompteResponse"/>
<xs:element name="consulterCompte" type="tns:consulterCompte"/>
<xs:element name="consulterCompteResponse"
type="tns:consulterCompteResponse"/>
<xs:element name="getAllComptes" type="tns:getAllComptes"/>
<xs:element name="getAllComptesResponse"
type="tns:getAllComptesResponse"/>
<xs:element name="retirer" type="tns:retirer"/>
<xs:element name="retirerResponse" type="tns:retirerResponse"/>
<xs:element name="verser" type="tns:verser"/>
<xs:element name="verserResponse" type="tns:verserResponse"/>
<xs:complexType name="getAllComptes">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="getAllComptesResponse">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="return"
type="tns:compte"/>
</xs:sequence>
</xs:complexType>
med@[Link]
Le schéma XML des données
échangées :
<xs:complexType name="compte">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="xs:long"/>
<xs:element minOccurs="0" name="dateCreation" type="xs:dateTime"/>
<xs:element name="solde" type="xs:double"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="consulterCompte">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="xs:long"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="consulterCompteResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="tns:compte"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="addCompte">
<xs:sequence>
<xs:element name="solde" type="xs:double"/>
</xs:sequence>
</xs:complexType>
med@[Link]
Le schéma XML des données
échangées :
<xs:complexType name="addCompteResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="tns:compte"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="retirer">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="xs:long"/>
<xs:element name="montant" type="xs:double"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="retirerResponse">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="verser">
<xs:sequence>
<xs:element minOccurs="0" name="code" type="xs:long"/>
<xs:element name="montant" type="xs:double"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="verserResponse">
<xs:sequence/>
</xs:complexType>
</xs:schema>
</wsdl:types> med@[Link]
Description des messages
<wsdl:message name="retirer">
<wsdl:part element="tns:retirer" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="retirerResponse">
<wsdl:part element="tns:retirerResponse"
name="parameters">
</wsdl:part>
</wsdl:message>
med@[Link]
L’élément PortType
<wsdl:portType name="BanqueService">
<wsdl:operation name="getAllComptes">
<wsdl:input message="tns:getAllComptes"
name="getAllComptes"></wsdl:input>
<wsdl:output message="tns:getAllComptesResponse"
name="getAllComptesResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="consulterCompte">
<wsdl:input message="tns:consulterCompte" name="consulterCompte">
</wsdl:input>
<wsdl:output message="tns:consulterCompteResponse"
name="consulterCompteResponse">
</wsdl:output>
</wsdl:operation>
………
</wsdl:portType>
med@[Link]
L’élément SoapBinding
<wsdl:binding name="BanqueServiceServiceSoapBinding"
type="tns:BanqueService">
<soap:binding style="document"
transport="[Link]
<wsdl:operation name="getAllComptes">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="getAllComptes">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getAllComptesResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="consulterCompte">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="consulterCompte">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="consulterCompteResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
…….
</wsdl:binding> med@[Link]
L’élément Service
<wsdl:service name="BanqueServiceService">
<wsdl:port
binding="tns:BanqueServiceServiceSoapBind
ing" name="BanqueServicePort">
<soap:address
location="[Link]
e/Banque
Service"/>
</wsdl:port>
</wsdl:service>
med@[Link]
Oxygen
<SOAP-ENV:Envelope xmlns:SOAP-
ENV="[Link]
nvelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<addCompte xmlns="[Link]
<solde xmlns="">3000</solde>
</addCompte>
</SOAP-ENV:Body>
</SOAP- Requête SOAP pour ajouter un compte
ENV:Envelope>
<soap:Envelope xmlns:soap="[Link]
<soap:Body>
<ns2:addCompteResponse xmlns:ns2="[Link]
<return>
<code>11</code>
<dateCreation>2013-06-05T[Link].469+01:00</dateCreation>
<solde>3000.0</solde>
</return>
</ns2:addCompteResponse>
</soap:Body>
</ Réponse SOAP après ajout d’un
soap:Envelop
e> compte
med@[Link]
Oxygen : Effectuer un
versement
<SOAP-ENV:Envelope xmlns:SOAP-
ENV="[Link]
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<verser xmlns="[Link]
<code xmlns="">1</code>
<montant xmlns="">9000</montant>
</verser>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope> Requête SOAP pour verser un montant
<soap:Envelope
xmlns:soap="[Link]
e/">
<soap:Body>
<ns2:verserResponse xmlns:ns2="[Link]
</soap:Body>
</soap:Envelope> Réponse SOAP
med@[Link]
Oxygen : Effectuer le
retrait
<SOAP-ENV:Envelope xmlns:SOAP-
ENV="[Link]
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<retirer xmlns="[Link]
<code xmlns="">1</code>
<montant xmlns="">600000</montant>
</retirer>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Requête SOAP pour retirer un montant>solde
<soap:Envelope
xmlns:soap="[Link]
e/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>[Link]
: Solde Insuffisant</faultstring>
</soap:Fault>
</ </soap:Envelope>
soap:Body>
Réponse SOAP
qui retourne
une exception
m
e
d
@
y
o
u
s
s
f
i
.
n
e
t
Oxygen : Consulter les Comptes
<SOAP-ENV:Envelope xmlns:SOAP-
ENV="[Link]
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<getAllComptes xmlns="[Link]
</SOAP-ENV:Body>
</SOAP- Requête SOAP pour consulter tous les
ENV:Envelope>
comptes
<soap:Envelope
xmlns:soap="[Link]
<soap:Body>
<ns2:getAllComptesResponse xmlns:ns2="[Link]
<return>
<code>1</code>
<dateCreation>2013-06-04T[Link]+01:00</dateCreation>
<solde>29000.0</solde>
</return>
<return>
<code>3</code>
<dateCreation>2013-06-04T[Link]+01:00</dateCreation>
<solde>15000.0</solde>
</return>
</ns2:getAllComptesResponse>
</ Réponse SOAP qui retourne une
soap:Body> exception
</
med@youssfi.
soap:Envelop net
e>
Client SOAP PHP
med@[Link]
Client PHP
<?php
try {
$clientSoap=new
SoapClient("[Link]
wsdl");
if(isset($_GET['action'])){
$operation=$_GET['action'];
if(($operation=="verser")||($operation=="retirer")){
$param1=new stdClass();
$param1->code=$_GET['code'];
$param1->montant=$_GET['montant'];
$clientSoap-> soapCall($operation, array($param1));
$param2=new stdClass();
$param2->code=$_GET['code'];
$repSoap=$clientSoap-> soapCall("consulterCompte", array($param2));
}
med@[Link]
Client PHP
else if($operation=="addCompte"){
$param1=new stdClass();
$param1->solde=$_GET['solde'];
$repSoap=$clientSoap-> soapCall($operation, array($param1));
}
else if($operation=="consulterCompte"){
$param1=new stdClass();
$param1->code=$_GET['code'];
$repSoap=$clientSoap-> soapCall($operation, array($param1));
}
}
else{
$repSoap=$clientSoap-> soapCall("getAllComptes", array());
}
} catch (Exception $e) {
}
?>
med@[Link]
Client PHP
<html>
<head>
</head>
<body>
<div>
<form action="[Link]" method="get">
Solde :<input type="text" name="solde">
<input type="submit" name="action" value="addCompte">
</form>
</div>
<div>
<form action="[Link]" method="get">
Code :<input type="text" name="code">
Montant :<input type="text" name="montant">
<input type="submit" name="action" value="consulterCompte">
<input type="submit" name="action" value="verser">
<input type="submit" name="action" value="retirer">
</form>
</div>
<a href="[Link]">Afficher tous les comptes</a>
med@[Link]
Client PHP
<table border="1" width="80%">
<tr>
<th>Code</th><th>Solde</th><th>Date Création</th>
</tr>
<?php
if(isset($repSoap)){
if(is_array($repSoap->return)){
$tab=$repSoap->return;
} else{
$tab=array($repSoap->return);
}
foreach ($tab as $cpte){?>
<tr>
<td><?php echo($cpte->code)?></td><td><?php echo($cpte->solde)?></td>
<td><?php echo($cpte->dateCreation)?></td>
</tr>
<?php } } ?>
</table>
<?php if(isset($e)){?> <li><?php echo ($e->getMessage())?></li> <?php }?>
</body></html>
med@[Link]
Client PHP
<table border="1" width="80%">
<tr>
<th>Code</th><th>Solde</th><th>Date Création</th>
</tr>
<?php
if(isset($repSoap)){
if(is_array($repSoap->return)){
$tab=$repSoap->return;
} else{
$tab=array($repSoap->return);
}
foreach ($tab as $cpte){?>
<tr>
<td><?php echo($cpte->code)?></td><td><?php echo($cpte->solde)?></td>
<td><?php echo($cpte->dateCreation)?></td>
</tr>
<?php } } ?>
</table>
<?php if(isset($e)){?> <li><?php echo ($e->getMessage())?></li> <?php }?>
</body></html>
med@[Link]
UDDI
med@[Link]
UDDI
L'annuaire des services UDDI est un
standard pour la publication et la
découverte des informations sur les
services Web.
La spécification UDDI est une
initiative lancée par ARIBA,
Microsoft et IBM.
Cette spécification n'est pas
gérée par le W3C mais par le
groupe OASIS.
La spécification UDDI vise à créer
une plate- forme indépendante, un
espace de travail (framework)
ouvert pour la description, la
découverte et l'intégration des
services des entreprises.
med@[Link]
Consultation de l'annuaire
L'annuaire UDDI se concentre sur le
processus de découverte de l'architecture
orientée services (SOA), et utilise des
technologies standards telles que XML,
SOAP et WSDL qui permettent de simplifier
la collaboration entre partenaires dans le
cadre des échanges commerciaux.
L'accès au référentiel s'effectue de
différentes manières.
◦ Les pages blanches comprennent la liste des
entreprises ainsi que des informations
associées à ces dernières (coordonnées,
description de l'entreprise, identifiants...).
◦ Les pages jaunes recensent les services Web
de chacune des entreprises sous le standard
WSDL.
◦ Les pages vertes fournissent des informations
techniques précises sur les services fournis.
med@[Link]
Architecture
Les entreprises publient les descriptions de leurs services Web
en UDDI, sous la forme de fichiers WSDL.
Ainsi, les clients peuvent plus facilement rechercher les
services Web dont ils ont besoin en interrogeant le registre
UDDI.
Lorsqu'un client trouve une description de service Web qui lui
convient, il télécharge son fichier WSDL depuis le registre
UDDI. Ensuite, à partir des informations inscrites dans le fichier
WSDL, notamment la référence vers le service Web, le client
peut invoquer le service Web et lui demande d'exécuter
certaines de ses fonctionnalités.
Le scénario classique d'utilisation de UDDI est illustré ci-
dessous. L'entreprise B a publié le service Web S, et
l'entreprise A est client de ce service :
Publication du Web
Service Découverte du Web Service
SOAP
SOAP
med@[Link]
Structures de données UDDI
Unregistre UDDI se compose de quatre
types de structures de données,
◦ le businessEntity,
◦ Le businessService,
◦ le bindingTemplate
◦ et la tModel.
med@[Link]
BusinessEntity
(entité d'affaires)
Les « businessEntities » sont
en quelque sorte les pages
blanches d'un annuaire UDDI.
Elles décrivent les organisations
ayant publié des services dans le
répertoire.
On y trouve notamment
◦ le nom de l'organisation,
◦ ses adresses (physiques et Web),
◦ des éléments de classification,
◦ une liste de contacts
◦ ainsi que d'autres informations.
med@[Link]
BusinessService
(service d'affaires)
Les « businessServices » sont en
quelque sorte les pages jaunes
d'un annuaire UDDI.
Elles décrivent de manière non
technique les services proposés par
les différentes organisations.
On y trouve essentiellement
◦ le nom et la description textuelle des
services
◦ ainsi qu'une référence à l'organisation
proposant le service
◦ et un ou plusieurs « bindingTemplate ».
med@[Link]
BindingTemplate (modèle
de rattachement)
UDDI permet de décrire des
services Web utilisant HTTP, mais
également des services invoqués
par d'autres moyens (SMTP, FTP...).
Les « bindingTemplates »
donnent les coordonnées des
services.
Ce sont les pages vertes de
l'annuaire UDDI.
Ils contiennent notamment une
description, la définition du point
d'accès (une URL) et les éventuels
« tModels » associés.
med@[Link]
tModel (index)
Les « tModels » sont les
descriptions techniques des
services.
UDDI n'impose aucun format
pour ces descriptions qui peuvent
être publiées sous n'importe quelle
forme et notamment sous forme de
documents textuels (XHTML, par
exemple).
C'est à ce niveau que WSDL
intervient comme le vocabulaire de
choix pour publier des descriptions
techniques de services.
med@[Link]
L'interface UDDI
L'interface UDDI est définie sous forme de
documents UDDI et implémentée sous forme
de service Web SOAP.
Elle est composée des modules suivants :
◦ Interrogation inquiry : Cette interface permet de
rechercher des informations dans un répertoire
UDDI.
◦ Publication : Cette interface permet de
publier des informations dans un
répertoire UDDI.
◦ Sécurité : cette interface est utilisée pour obtenir
et révoquer les jetons d'authentification
nécessaires pour accéder aux enregistrements
protégés dans un annuaire UDDI.
◦ Contrôle d'accès et propriété custody and
ownership transfer: Cette interface permet de
transférer la propriété d'informations (qui est à
l'origine attribuée à l'utilisateur ayant publié ces
informations) et de gérer les droits d'accès
associés.
◦ Abonnement Subscription : Cette interface
permet à un client de s'abonner à un ensemble
d'informations et d'être averti lors des modifications
de ces informations.
med@[Link]
WEB SERVICES REST
FULL
med@[Link]
RESTful
REST (REpresentational State
Transfer) ou RESTful est un style
d’architecture pour les systèmes
hypermédia distribués,
Créé par Roy Fielding en 2000 dans le
chapitre 5 de sa thèse de doctorat.
REST est un style d’architecture permettant
de construire des applications (Web,
Intranet,Web Service).
Il s’agit d’un ensemble de conventions et
de bonnes pratiques à respecter et non
d’une technologie à part entière.
L’architecture REST utilise les spécifications
originelles du protocole HTTP, plutôt que
de réinventer une surcouche (comme le
font SOAP ou XML-RPC par exemple).
med@[Link]
REST: Principe
Description du Service Web
permettant de générer la partie
cliente
med@[Link]
Règle N°1 :
l’URI comme identifiant des
ressources
med@[Link]
Règle N°1 :
Quelques exemples de construction d’URL avec
RESTful :
med@[Link]
Règle n°2 : les verbes HTTP comme
identifiant des opérations
Exemple d’URL pour une ressource donnée
(un livre par exemple) :
Créer un livre
NOK : GET [Link]
OK : POST [Link]
Afficher
◦ NOK : GET [Link]
◦ OK : GET [Link]
Mettre à jour
◦ NOK : POST [Link]
◦ OK : PUT [Link]
Supprimer
◦ NOK : GET [Link]
◦ OK : DELETE [Link]
med@[Link]
Règle n°3 : les réponses HTTP
comme représentation des
ressources
Il est important d’avoir à l’esprit que la
réponse envoyée n’est pas une ressource,
c’est la représentation d’une ressource.
Ainsi, une ressource peut avoir plusieurs
représentations dans des formats divers :
HTML, XML, CSV, JSON, etc.
C’est au client de définir quel format de réponse
il souhaite reçevoir via l’entête Accept.
Il est possible de définir plusieurs formats.
◦ Réponse en HTML
GET /books
Host:
[Link]
Accept: text/html
◦ Réponse en XML
GET /books
Host: [Link]
Accept:
application/xml
med@[Link]
Règle n°4 : les liens comme
relation entre ressources
Les liens d’une ressource vers une autre ont tous une chose
en commun
: ils indiquent la présence d’une relation.
Il est cependant possible de la décrire afin d’améliorer la
compréhension du système.
Pour expliciter cette description et indiquer la nature
de la relation, l’attribut rel doit être spécifier sur tous
les liens.
Ainsi l’IANA donne une liste de relation parmi lesquelles :
◦ contents
◦ edit
◦ next
◦ last
◦ payment
◦ etc.
La liste complète sur le site de l’IANA :
◦ [Link]
[Link]
med@[Link]
Règle n°4 : les liens comme
relation entre ressources
Exemple de réponse en XML d’une liste
paginée de livres :
<?xml>
<search>
<link rel="self" title="self" href="[Link] />
<link rel="next" title="next" href="[Link] />
<link rel="last" title="last" href="[Link] />
<book>
//...
</book>
</search>
med@[Link]
Règle n°5 : un paramètre comme
jeton d’authentification
C’est un des sujets les plus souvent abordé
quand on parle de REST : comment authentifier
une requête ?
La réponse est très simple et est massivement
utilisée par des APIs renommées
(Google,Yahoo, etc.) : le jeton
d’authentification.
Chaque requête est envoyée avec un jeton
(token) passé en paramètre $_GET de la
requête.
Ce jeton temporaire est obtenu en envoyant
une première requête d’authentification puis en
le combinant avec nos requêtes.
Ainsi, on peut construire le scénario suivant :
med@[Link]
Règle n°5 : un paramètre comme
jeton d’authentification
1. demande d’authentification
◦ GET /users/123/authenticate?
pass=lkdnssdf54d47894f5123002fds2sd360s0
<?xml>
<user>
<id>123</id>
<name>Nicolas Hachet</name>
</user>
<token>
fsd531gfd5g5df31fdg3g3df45
</token>
JSON
[
{type:"courant" , code:1, solde:4300.50,dateCreation:"2012-11-11"},
{type:"epargne" , code:1, solde:4300.00,dateCreation:"2012-11-11"}
]
med@youssfi.
Structures de JSON
JSON se base sur deux structures :
◦Une collection de couples nom/valeur.
◦Divers langages la réifient par un
objet, un enregistrement, une
structure, un dictionnaire, une table
de hachage, une liste typée ou un
tableau associatif.
Ces structures de données sont
universelles. Pratiquement tous
les langages de programmation
modernes les proposent sous une
forme ou une autre.
med@[Link]
Les structures de données
JSON
EnJSON, les structures de données prennent
les formes suivantes :
◦ Un objet, qui est un ensemble de couples
nom/valeur non ordonnés. Un objet commence par {
(accolade gauche) et se termine par } (accolade
droite). Chaque nom est suivi de : (deux- points) et
les couples nom/valeur sont séparés par , (virgule).
◦ Un tableau est une collection de valeurs
ordonnées. Un tableau commence par [ (crochet
gauche) et se termine par ] (crochet droit). Les
valeurs sont séparées par , (virgule).
◦ Une valeur peut être soit une chaîne de
caractères entre guillemets, soit un nombre,
soit true ou false ou null, soit
un objet soit un tableau. Ces structures peuvent être
imbriquées.
◦ Une chaîne de caractères est une suite de zéro
ou plus caractères Unicode, entre guillemets, et
utilisant les échappements avec antislash. Un
caratère est représenté par une chaîne d'un seul
caractère.
med@[Link]
Structure des données JSON
med@[Link]
Structure des données JSON
med@[Link]
Généralités sur JAX RS
Le développement de Services Web
avec JAX-RS est basé sur des POJO
(Plain Old Java Object) en utilisant des
annotations spécifiques à JAX-RS
Pas description requise dans des
fichiers de configuration
Seule la configuration de la Servlet «
JAX-RS » est requise pour réaliser le pont
entre les requetés HTTP et les classes
Java annotées
Un Service Web REST est déployé
dans une application Web
med@[Link]
Généralités sur JAX RS
Contrairement aux Services Web
entendus il n’y a pas de possibilité de
développer un service REST à partir du
fichier de description WADL
Seule l’approche Botton / Up est
disponible
◦ Créer et annoter un POJO
◦ Compiler, Déployer et Tester
◦ Possibilité d’accéder au document WADL
Le fichier de description WADL est
génèré automatiquement par JAX-
RS (exemple :
[Link]
l)
med@[Link]
Exemple de web service
RESTful
Consulter un compte
Consulter la liste des comptes
Effectuer un versement
Effectuer un retrait
Effectuer un virement
Supprimer un compte
med@[Link]
Exemple de web service
JAX RS
package [Link];
import [Link].*; import [Link].*;
import [Link];
import
[Link];
import [Link];
import [Link];
import
[Link];
@Component
@Path("/banque
")
public class BanqueRestService {
@Autowired
IBanqueMetier metier;
@POST
@Path("/comptes")
public void addCompte(@FormParam(value="solde")double solde){
[Link](new Compte(null, solde,new Date()));
}
med@[Link]
Exemple de web service JAX RS
@GE
T
@Path("/comptes/{code}")
@Produces(value={MediaType.APPLICATION_JSON,MediaType.APPLICATION_
XML}) public Compte getCompte(@PathParam(value="code")Long code){
return [Link](code);
}
@GE
T
@Path("/comptes")
@Produces(value={MediaType.APPLICATION_JSON,MediaType.APPLICATION_
XML}) public List<Compte> getComptes(){
return [Link]();
}
@PU
T
@Path("/comptes/verser")
public void verser(@FormParam("code") Long code,@FormParam("montant")
double montant){
[Link](code, montant);
}
med@[Link]
Exemple de web service JAX RS
@PU
T
@Path("/comptes/retirer")
public void retirer(@FormParam("code") Long
code,@FormParam("montant") double montant){
[Link](code, montant);
}
@PU
T
@Path("/comptes/virement")
@Produces(value={MediaType.APPLICATION_JSON,[Link]
_XML}) public void virement(@FormParam("cpte1") Long cpte1,
@FormParam("cpte2") Long cpte2,
@FormParam("montant") double montant){
[Link](cpte1, cpte2, montant);
}
@DELET
E
@Path("/comptes/{code}")
public void supprimer(@PathParam("code")Long code){
[Link](code);
}
}
med@[Link]
Maven Dependencies
<!-- Jersey -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>jersey-server</artifactId>
<version>1.8</version>
</dependency>
<!-- Jackson -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>jackson-jaxrs-json-provider</
artifactId>
<version>2.3.0</version>
</dependency>
med@[Link]
Maven Dependencies
<!-- Jersey + Spring -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>jersey-spring</artifactId>
<version>1.8</version>
<exclusions>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>spring</artifactId>
</exclusion>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>[Link]</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>
med@[Link]
[Link]
<!-- Jersey Container-->
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>
[Link]
</servlet-class>
<init-param>
<param-name>[Link]</param-name>
<param-value>[Link]</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
med@[Link]
Consulter les comptes avec une requête http GET
med@youssfi.
Consulter un comptes avec une requête http GET
med@[Link]
Récupérer la représentation json
d’un compte avec une requête
http GET
med@[Link]
Récupérer la représentation json
des comptes avec une requête
http GET
med@[Link]
Ajouter un compte avec requête http
POST
med@[Link]
WADL :Web Application
Description Language
WADL est un fichier XML qui permet de
faire la description des services web
d’une application basée sur REST.
Le WADL est généré automatiquement
par le conteneur REST.
[Link]
[Link]
Les types de données structurés
échangés via ce web service sont
décrites par un schéma XML lié au
WSDL.
Le schéma xml de l’application REST
peut être consulté par l’adresse de
suivante :
[Link]
med@[Link]
Récupérer le WADL
med@[Link]
Structure du DADL
med@[Link]
Structure du WADL
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="[Link]
<doc xmlns:jersey="[Link] jersey:generatedBy="Jersey: 1.8
06/24/2011 12:17 PM"/>
<resources base="[Link]
<resource path="/banque">
<resource path="/comptes">
<method id="addCompte" name="POST">
<request>
<representation mediaType="application/x-www-form-urlencoded">
<param xmlns:xs="[Link]
name="solde" style="query" type="xs:double"/>
</representation>
</request>
</method>
<method id="getComptes" name="GET">
<response>
<representation mediaType="application/json"/>
<representation mediaType="application/xml"/>
</response>
</method>
</resource>
med@[Link]
Structure du WADL
<resource path="/comptes/{code}">
<param xmlns:xs="[Link] name="code"
style="template" type="xs:long"/>
<method id="getCompte" name="GET">
<response>
<representation mediaType="application/json"/>
<representation mediaType="application/xml"/>
</response>
</method>
<method id="supprimer" name="DELETE"/>
</resource>
<resource path="/comptes/verser">
<method id="verser" name="PUT">
<request>
<representation mediaType="application/x-www-form-urlencoded">
<param xmlns:xs="[Link]
name="code" style="query" type="xs:long"/>
<param xmlns:xs="[Link]
name="montant" style="query" type="xs:double"/>
</representation>
</request>
</method>
</resource>
med@[Link]
Structure du WADL
<resource path="/comptes/retirer">
<method id="retirer" name="PUT">
<request>
<representation mediaType="application/x-www-form-urlencoded">
<param xmlns:xs="[Link]
name="code" style="query" type="xs:long"/>
<param xmlns:xs="[Link]
name="montant" style="query" type="xs:double"/>
</representation>
</request>
</method>
</resource>
med@[Link]
Structure du WADL
<resource path="/comptes/virement">
<method id="virement" name="PUT">
<request>
<representation mediaType="application/x-www-form-urlencoded">
<param xmlns:xs="[Link]
name="cpte1" style="query" type="xs:long"/>
<param xmlns:xs="[Link]
name="cpte2" style="query" type="xs:long"/>
<param xmlns:xs="[Link]
name="montant" style="query" type="xs:double"/>
</representation>
</request>
</method>
</resource>
</resource>
</resources>
</application>
med@[Link]
Client Java JaxRS
med@[Link]
Maven dependencies
<!-- Jersey Client -->
<dependencies>
<dependency>
<groupId>[Link]</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18</version>
</dependency>
<!-- Google JSON API -->
<dependency>
<groupId>[Link]</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
</dependencies>
med@[Link]
Code Java d’un client
JaxRS
package jerseyTest;
import [Link]; import [Link];
import [Link]; import [Link];
import [Link]; import
[Link]; import
[Link]; import
[Link];
med@youssfi.
Client HTML5,
JQUERY SGB
D
Couche DAO
Couche Métier
Service REST
HTTP
JSON
HTML, JQUERY
med@[Link]
[Link]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="jquery/[Link]"></script>
<script type="text/javascript" src="js/[Link]"></script>
</head>
<body>
<input type="button" value="charger Les comptes" onclick="chargerComptes()">
<div id="listComptes">
<table>
<thead>
<tr>
<th>Numéro</th><th>Solde</th><th>Date Création</th>
</tr>
</thead>
<tbody id="tableBody">
</tbody>
</table>
</div>
</body>
</html>
[Link]
function chargerComptes(){
$.getJSON("[Link]
$("#tableBody").html("");
for(i in data){
$tr=$("<tr>");
$td=$("<td>").append(data[i]['code']);$[Link]($td);
$td=$("<td>").append(data[i]['solde']);$[Link]($td);
$td=$("<td>").append(data[i]['dateCreation']);$[Link]($td);
$("#tableBody").append($tr);
}
});
}
med@[Link]
Client
Androïde SGB
D
Couche DAO
Couche Métier
Service WEB
HTTP
JSON
Client Mobile
Androide
med@[Link]
Vue
med@[Link]
L’activité
package [Link];
import [Link].*;import [Link].*;import
[Link].*; import
[Link];
import [Link];
import [Link].*;import [Link].*;import
[Link]; import [Link].*;import
[Link]; import [Link].*;
med@[Link]
@Path
Une classe Java doit être annotée par @path pour
qu’elle puisse être traitée par des requêtes HTTP
L’annotation @path sur une classe définit des ressources
appelées racines (Root Resource Class)
La valeur donnée à @path correspond à une expression
URI relative au contexte de l’application Web
L’annotation @path peut également annoter des
méthodes de la classe (facultatif)
L’URI résultante est la concaténation de l’expression du
@path de la classe avec l’expression du @path de la
méthode
[Link]
med@[Link]
@Path :Template Parameters
package service; EXEMPLE
import [Link].*;
@Path("/biblio")
public class BookResource {
@GET
@Path("{id}")
public String getBookById(@PathParam("id") int id){
return "Book Id="+id;
}
@GET
@Path("name={name}&editor={editor}")
public String getBookByNameAndEditor(@PathParam("name") String name,@PathParam("editor") String editor){
return "Book Name="+name+" Editor="+editor;
}
}
med@[Link]
Mé́thodes HTTP : @GET, @POST, @PUT, @DELETE
med@[Link]
Paramè̀tres de requê̂tes
JAX-RS fournit des annotations pour
extraire des paramètres d’une requête
Elles sont utilisées sur les paramètres des
méthodes des ressources pour réaliser
l’injection du contenu
Liste des différentes annotations disponibles :
◦ @PathParam : extraire les valeurs des Template
Parameters
◦ @QueryParam : extraire les valeurs des paramètres de
requête
◦ @FormParam : extraire les valeurs des paramètres de
formulaire
◦ @HeaderParam : extraire les paramètres de l’entête
◦ @CookieParam : extraire les paramètres des cookies
◦ @Context : extraire les informations liées aux
ressources de contexte
Une valeur par défaut peut être spécifiée
en utilisant l’annotation @DefaultValue
med@[Link]
L’annotation @pathparam
L’annotation @PathParam est utilisée pour extraire les
valeurs des paramètres contenues dans les
Template Parameters
package service;
import [Link].*;
@Path("/biblio")
public class BookResource {
@GET
@Path("/bookById/{id}")
public String getBookById(@PathParam("id") int id){
return "Book Id="+id;
}
@GET
@Path("/book/name-{name}:editor-{editor}")
public String getBookByNameAndEditor(@PathParam("name") String name,@PathParam("editor") String editor){
return "Book Name="+name+" Editor="+editor;
}
}
med@[Link]
L’annotation @queryparam
L’annotation @QueryParam est utilisée pour extraire
les valeurs des paramètres contenues d’une requête
quelque soit son type de méthode HTTP
@GET
public String getQueryParameterBook(
@DefaultValue("all")@QueryParam("name")String name,
@DefaultValue("true")@QueryParam("isReady")boolean isReady )
{ return "Name="+name+" ready="+isReady;
}
med@[Link]
Paramè̀tres de requê̂tes : @FormParam
@GET
public String getQueryParameterBook(
@DefaultValue("all")@QueryParam("name")String name,
@DefaultValue("true")@QueryParam("isReady")boolean isReady,
@HeaderParam("User-Agent") String userAgent ){
return "Name="+name+" ready="+isReady+" Agent="+userAgent;
}
med@[Link]
Paramètres de requê̂tes :
@Context
med@[Link]
Paramè̀tres de requê̂tes :
@Context / UriInfo
Un objet de type UriInfo permet
d’extraire les informations « brutes »
d’une requête HTTP
Les principales méthodes sont les suivantes :
◦ String getPath() : chemin relatif de la requête
◦ MultivaluedMap<String, String>
getPathParameters() : valeurs des
paramètres de la requête contenues dans
Template Parameters
◦ MultivaluedMap<String, String>
getQueryParameters() : valeurs des
paramètres de la requête
◦ URI getBaseUri() : chemin de l’application
◦ URI getAbsolutePath() : chemin
absolu (base + chemins)
◦ URI getRequestUri() : chemin absolu
incluant les paramètres
med@[Link]
Paramè̀tres de requê̂tes :@Context / UriInfo
@GET
@Path("/uriInfo/{name}")
public String uriInfo(@Context UriInfo uriInfo, @PathParam("name")String name){
[Link]("getPath() :"+[Link]());
[Link]("getAbsolutePath():"+[Link]());
[Link]("getBaseUri():"+[Link]());
[Link]("ggetRequestUri():"+[Link]());
[Link]("getPathSegments():");
List<PathSegment> pathSegments=[Link]();
for(PathSegment ps:pathSegments)
[Link]([Link]());
[Link]("getPathParameters()");
MultivaluedMap<String, String> parameters=[Link]();
for(String key:[Link]())
[Link](key+"="+[Link](key));
return "OK";
}}}
med@[Link]
Paramè̀tres de requê̂tes :@Context / UriInfo
getPath() : biblio/uriInfo/a
getAbsolutePath():
[Link] getBaseUri():
[Link]
ggetRequestUri():
[Link]
getPathSegments():
biblio
uriInf
oa
getPathParameters()
name=[a]
med@[Link]
Paramè̀tres de
requê̂tes : @Context /
HttpHeaders
Un objet de type HttpHeader permet
d’extraire les informations contenues
dans l’entête d’une requête
Les principales méthodes sont les suivantes:
◦ Map<String, Cookie> getCookies() : les
cookies de la requête
◦ Locale getLanguage() : le langue de la requête
◦ MultivaluedMap<String, String>
getRequestHeaders() : valeurs des
paramètres de l’entête de la requête
◦ MediaType getMediaType() : le type MIME de la
requête
A noter que ces méthodes permettent
d’obtenir le même résultat que les
annotations @HeaderParam et
@CookieParam
med@[Link]
Paramè̀tres de requê̂tes :@Context /
UriInfo
@GET
@Path("httpHeaders")
public String getInformationFromHttpHeaders(@Context HttpHeaders httpheaders) {
Map<String, Cookie> cookies = [Link]();
Set<String> currentKeySet = [Link]();
for (String currentCookie : currentKeySet) {
[Link](currentCookie+"="+[Link](currentCookie));
}
MultivaluedMap<String, String> requestHeaders = [Link]();
Set<String> requestHeadersSet = [Link]();
for (String currentHeader : requestHeadersSet) {
[Link](currentHeader+"="+[Link](currentHeader));
}
return "ok";
}
• host=[localhost:8080]
• connection=[keep-alive]
• cache-control=[max-age=0]
• accept=[text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8]
• user-agent=[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.31 (KHTML, like Gecko)
Chrome/26.0.1410.65 Safari/537.31]
• accept-encoding=[gzip,deflate,sdch]
• accept-language=[fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4]
• accept-charset=[ISO-8859-1,utf-8;q=0.7,*;q=0.3]
med@[Link]
Repré́sentations :
@Consumes,
@Produces
L’annotation @Consumes est utilisée pour
spécifier le ou les types MIME qu’une méthode
d’une ressource peut accepter
L’annotation @Producer est utilisée pour
spécifier le ou les types MIME qu’une méthode
d’une ressource peut produire
Possibilité de définir un ou plusieurs types MIME
Ces annotations peuvent être portées sur une
classe ou sur une méthode
L’annotation sur la méthode surcharge celle de la
classe
Si ces annotations ne sont pas utilisées tous
types MIME pourront être acceptés ou
produits
La
liste des constantes des différents type
MIME est disponible dans la classe
MediaType
med@[Link]
Repré́sentations :
@Consumes,
@Produces
Requête HTTP
<html>
…
</html>
med@[Link]
Repré́sentations : @Consumes,
@Produces
package service;
import [Link].*;
import [Link].*; @GET
import [Link]; @Path("/infos")
@Path("/banque") @Produces(MediaType.APPLICATION_JSON)
public class RestService { public List<String> getInfos(){
List<String> res=new ArrayList<String>();
@GET
[Link]("A");[Link]("B");[Link]("C");
@Path("/message")
return res;
@Produces(MediaType.TEXT_PLAIN) }
public String getMessage(){ @GET
return "Test Rest full"; @Path("/clients")
} @Produces(MediaType.APPLICATION_XML)
public List<Client> getClients(){
@GET
List<Client> res=new ArrayList<Client>();
@Path("/conversion/{montant}")
[Link](new Client(1,"A"));
@Produces(MediaType.APPLICATION_JSON) return res;
public double conversion (@PathParam("montant") double }
mt){ }
return mt*11;
}
package service;
import [Link];import [Link];
@XmlRootElement
public class Client implements Serializable {
private int code;
private String nom;
// Getters , Setters et Constructeurs
} med@[Link]
Accès au service avec un
browser
Format JSON
Format Text
Format JSON
med@[Link]
Accès au service avec un
browser
Format XML
med@[Link]
Gestion du contenu : statu des
réponses
Lors de l’envoie de la réponse au client un code
statut est retourné
Réponse sans erreur : Les statuts des réponses
sans erreur s’échelonnent de 200 à 399
◦ Le code est 200 « OK » pour les services retournant un
contenu non vide
◦ Le code est 204 « No Content » pour les services
retournant un contenu vide
Réponse avec erreur : Les statuts des réponses
avec erreur s’échelonnent de 400 à 599
◦ Une ressource non trouvée, le code de retour est 404 « Not
Found »
◦ Un type MIME en retour non supporté, 406 « Not Acceptable »
◦ Une méthode HTTP non supportée, 405 « Method Not Allowed
»
med@[Link]
Response
JAX-RS
facilite la construction de réponses en
permettant de
◦ de choisir un code de retour
◦ de fournir des paramètres dans l’entête
◦ de retourner une URI, ...
Lesréponses complexes sont définies par la classe
Response
disposant de méthodes abstraites non utilisables
directement
◦ Object getEntity() : corps de la réponse
◦ int getStatus() : code de retour
◦ MultivalueMap<String, Object> getMetaData() : données de
l’entête
Les
informations de ces méthodes sont
obtenues par des méthodes statiques
retournant des ResponseBuilder
Utilisation du patron de conception Builder
med@[Link]
Principales méthodes de Response
ResponseBuilder created(URI location) : Modifie
la valeur de Location dans l’entête, à utiliser pour
une nouvelle ressource créée
ResponseBuilder notModified() : Statut à « Not
Modified »
ResponseBulder ok() : Statut à « Ok »
ResponseBuilder serverError() : Statut à « Server Error
»
ResponseBuilder status([Link]) :
défini un statut particulier défini dans
[Link]
med@[Link]
Méthodes de ResponseBuilder
med@[Link]
Exemple de Response
@Path("response")
@GET
public Response gerReponse(){
return Response
.status([Link])
.header("param1", "valeur1")
.header("param2", "valeur2")
.entity("Corps du message")
.build();
}
med@[Link]
Exemple de Response
@GE
T
@Path("/comptes/v2/{code}")
@Produces(value={MediaType.APPLICATION_JSON,MediaType.APPLICATION_
XML}) public Response compte(@PathParam(value="code")Long code){
Compte
cp=[Link](code);
return Response
.status([Link])
.entity(cp)
.build();
}
med@[Link]
Développement Client : la
création de la requête
La création de la requête s’appuie sur la patron Builder
Création d’une chaine d’appel de méthodes dont le type de
retour est
WebResource ou [Link]
La chaine d’appel se termine par les méthodes
correspondant aux méthodes HTTP (GET, POST, ...)
La classe [Link] contient les méthodes de
terminaison
◦ <T> get(Class<T> c) : appelle méthode GET avec un type de retour T
◦ <T> post(Class<T> c, Object entity) : appelle méthode POST en
envoyant un contenu dans la requête
◦ <T> put(Class<T> c, Object entity) : appelle méthode PUT en envoyant
un contenu dans la requête
◦ <T> delete(Class<T> c, Object entity) : appelle méthode DELETE
en envoyant un contenu dans la requête
med@[Link]
Développement Client : la
création de la requête
La classe WebResource
fournit des méthodes pour
construire l’entête de la requête
Principales méthodes de
WebResource:
◦ WebResource path(String) : définition d’un chemin
◦ WebResource queryParam(String key, String val) : paramètre
requête
◦ Builder accept(MediaType) : type supporté par le client
◦ Builder header(String name, Object value) : paramètre entête
◦ Builder cookie(Cookie cookie) : ajoute un cookie
med@[Link]
Client java REST: Méthodes POST et PUT
package service;
import [Link];
import [Link];
@XmlRootElement
public class Client implements Serializable {
private int code;
private String nom;
// Constructeurs, Getters et Setters
}
med@[Link]
Client java REST:
ClientResponse
[Link](" ");
WebResource path4=[Link]("banque").path("response");
ClientResponse res4=[Link]([Link]);
MultivaluedMap<String, String> headers=[Link]();
[Link]([Link]("param1"));
[Link]([Link]("param2"));
[Link]([Link]([Link]));
med@[Link]
Problème
On souhaite Créer une application distribuée qui
permet de gérer le transport des cargaisons
contenant des marchandises. Chaque cargaison
contient plusieurs marchandises. Il existe deux
types de cargaisons : les cargaisons routières et
aériennes.
Chaque marchandise est définie par un numéro
de type Long (Auto Incrémenté), le nom de la
marchandise, son poids et son volume.
Chaque cargaison est définie par une
référence de type String, la distance de
parcours, la date de livraison.
Une cargaison routière est une cargaison qui
possède en plus la température de conservation.
Une cargaison aérienne est une cargaison qui
possède en plus un poids maximal qui ne doit
pas être dépassé.
med@[Link]
Problème
L’application se compose de des couches suivantes :
Une couche métier basées sur EJB (Entity et Session)
Une couche service qui permet un accès distant
aux services métiers qui contient deyx types de
services :
◦ Un web service SOAP avec JAXWS
◦ Un web service REST FULL basé sur JAXRS
Pour accéder aux services de cette application,
d’autres entreprises peuvent développer des
applications clientes de différents types :
◦ Un client Mobile Androide
◦ Un client PHP qui permet de consulter les marchandises dont le
nom contient un mot clé. Cette application fait appel à la
couche métier via le service SOAP
◦ Un client Java qui permet d’ajouter les cargaisons et les
marchandises en faisant appel au service REST FULL (Format
généré : JSON)
◦ Un client WEB (HTML, CSS, JQUERY) qui permet de consulter les
marchandises d’une cargaison sélectionnée dans une liste
déroulante. Cette application s’appuie sur le service REST FULL
med@[Link]
Architecture
Seveur d’application J2EE : JBOSS MYSQL
(http :8080)
Couche Hiberna
Service Web te JDBC
Service SOAP
Web Service JNDI
REST
HTT
HTTP P
JSON JSO
N
Client Java
Client Android
he :8888
Apa PHP
SOAP
c
HTTP
med@[Link]
Diagramme de classes
med@[Link]
Base de données
Démarrer Easy PHP
◦MySQL
◦Apache
◦PHP
◦PhpMyAdmin
Créer la base de
données
DB_TRANSPORT
Les tables seront créées par le
framework de mapping objet
relationnel (Hibernate)
med@[Link]
Déployer le DataSource
med@[Link]
Projet Web Dynamique
med@[Link]
Structure du projet
med@[Link]
Entity : Marchandise
package [Link]; import [Link]; import
[Link].*; @Entity
@Table(name="MARCHANDISES")
public class Marchandise implements
Serializable { @Id
@GeneratedValue(strategy=[Link]
TY) @Column(name="NUMERO")
private Long numero;
@Column(name="NOM")
private String nom;
private double poids;
private double volume;
@ManyToOne
@JoinColumn(name="REF_CARG")
private Cargaison cargaison;
public Marchandise(String nom, double poids, double
volume) { [Link] = nom;[Link] = poids; [Link]
= volume;
}
public Marchandise() {super(); }
// Geters et Setters
} med@[Link]
Entity : Cargaison
package [Link];import [Link].*;import
[Link].*; import [Link].*;import
[Link].*; import
[Link];
@Entity
@Table(name="CARGAISONS")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE_CARG")
@XmlAccessorType([Link])
@XmlSeeAlso({[Link],[Link]
}) public abstract class Cargaison implements Serializable{
@Id
@Column(name="REF_CARG"
)
private String reference; private int distance; private Date
dateLivraison; @OneToMany(mappedBy="cargaison",fetch=[Link])
@XmlTransient
private Collection<Marchandise> marchandises;
public Cargaison(String reference, int distance, Date dL) {
[Link] = reference; [Link] = distance; [Link] = dL;
} public Cargaison()
{} @JsonIgnore
public Collection<Marchandise> getMarchandises() { return marchandises;} //Get et
Set}
Entity : CargaisonAerienne
package [Link];
import [Link];
import
[Link].*;
@Entity
@DiscriminatorValue("CA")
public class CargaisonAerienne extends
Cargaison { private double poidsMax;
public CargaisonAerienne(String reference, int distance, Date
dateLivraison, double poidsMax) {
super(reference, distance,
dateLivraison); [Link] = poidsMax;
}
public CargaisonAerienne() {
}
// Getters et Setters
}
Entity : CargaisonRoutiere
package [Link];
import [Link];
import
[Link].*;
@Entity
@DiscriminatorValue("CR")
public class CargaisonRoutiere extends
Cargaison { private float
temperatureConservation;
public CargaisonRoutiere(String reference, int distance, Date
dateLivraison, float temperatureConservation) {
super(reference, distance, dateLivraison);
[Link] = temperatureConservation;
}
public CargaisonRoutiere() {
}
// Getters et Setters
}
[Link]
Le dossier META-INF devrait être ajouté au classpath :
CAGAISONS :
med@[Link]
Traitements Métier
Interface Local
package
[Link];
import [Link];
import [Link];
@Local
public interface ITransportLocal {
public void addCargaison(Cargaison
c);
public void addMarchandise(Marchandise m,String
refCarg); public List<Cargaison> getAllCargaisons();
public List<Marchandise> getMarchandisesParCarg(String
refCarg); public Cargaison getCargaison(String reg);
public void supprimerMarchandise(Long numeroMarch);
}
med@[Link]
Traitements Métier
EJB Session Statless
package [Link];import [Link];
import [Link];import
[Link].*; @Stateless(name="TRANS")
public class TransportEJBImpl implements ITransportLocal {
@PersistenceContext(unitName="UP_TRANSPORT")
EntityManager em;
@Override
public void addCargaison(Cargaison c)
{ [Link](c);
}
@Override
public void addMarchandise(Marchandise m, String refCarg) {
Cargaison c=[Link]([Link], refCarg);
[Link](c);[Link](m);
}
@Override
public List<Cargaison> getAllCargaisons() {
Query req=[Link]("select c from Cargaison
c"); return [Link]();
} med@youssfi.
Traitements Métier
EJB Session Statless
@Override
public List<Marchandise> getMarchandisesParCarg(String refCarg)
{
Query req=[Link]
("select m from Marchandise m where [Link]=:x");
[Link]("x", refCarg);
return [Link]();
}
@Override
public Cargaison getCargaison(String
reg) { Cargaison
c=[Link]([Link], reg); return
c;
}
@Override
public void supprimerMarchandise(Long numeroMarch) {
Marchandise m=[Link]([Link],
numeroMarch); [Link](m);
}
}
med@[Link]
Couche Service
med@[Link]
Web Service SOAP
package [Link];import [Link].*;
import [Link].*;import [Link].*;import [Link].*;
@Stateless
@WebService
public class TransportSOAPService
{ @EJB
private ITransportLocal
metier; @WebMethod
public void ajouterCargaisonRoutiere(
@WebParam(name="ref")String ref,
@WebParam(name="distance")int dist,
@WebParam(name="dateLivraison")Date dateLiv,
@WebParam(name="tempConserv")float temp){
CargaisonRoutiere cr=new CargaisonRoutiere(ref, dist, dateLiv, temp);
[Link](cr);
}
med@[Link]
Web Service SOAP
@WebMethod
public void ajouterCargaisonAerienne(
@WebParam(name="ref")String ref,
@WebParam(name="distance")int dist,
@WebParam(name="dateLivraison")Date dateLiv,
@WebParam(name="poidsMax")float poids){
CargaisonAerienne ca=new CargaisonAerienne(ref, dist, dateLiv, poids);
[Link](ca);
}
@WebMethod
public void ajouterMarchandise(
@WebParam(name="nom")String nom,
@WebParam(name="poids")double poids,
@WebParam(name="volume")double volume,
@WebParam(name="refCarg")String refCarg){
Marchandise m=new Marchandise(nom, poids, volume);
[Link](m, refCarg);
}
med@[Link]
Web Service SOAP
@WebMethod
public List<Cargaison>
getAllCargaisons(){ return
[Link]();
}
@WebMethod
public List<Marchandise> getMarchParCarg(
@WebParam(name="refCarg")String refCarg){
return
[Link](refCarg);
}
@WebMethod
public Cargaison consulterCargaison(
@WebParam(name="refCarg")String refCarg){
return [Link](refCarg);
}
@WebMethod
public void supprimerMarchandise(
@WebParam(name="numMarch")Long
numero){
[Link](numero);
}}
med@[Link]
Redéployer le projet
WSDL
med@[Link]
Tester les méthodes avec le
client SOAP Oxygen
med@youssfi.
Requête SOAP pour ajouter les
cargaisons et les marchandises
<SOAP-ENV:Envelope xmlns:SOAP-
ENV="[Link]
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ajouterCargaisonRoutiere xmlns="[Link]
<ref xmlns="">CR2</ref>
<distance xmlns="">120</distance>
<dateLivraison xmlns="">2011-12-11</dateLivraison>
<tempConserv xmlns="">22</tempConserv>
</ajouterCargaisonRoutiere>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
med@[Link]
Requête SOAP pour ajouter les
cargaisons et les marchandises
<SOAP-ENV:Envelope xmlns:SOAP-ENV="[Link]
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<ajouterCargaisonAerienne xmlns="[Link]
<ref xmlns="">CA2</ref>
<distance xmlns="">123</distance>
<dateLivraison xmlns="">2012-12-13</dateLivraison>
<poidsMax xmlns="">200</poidsMax>
</ajouterCargaisonAerienne>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
med@[Link]
Requête SOAP pour consulter toutes les cargaisons
<SOAP-ENV:Envelope xmlns:SOAP-ENV="[Link]
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<getAllCargaisons xmlns="[Link]
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<soap:Envelope xmlns:soap="[Link]
<soap:Body>
<ns2:getAllCargaisonsResponse xmlns:ns2="[Link]
<return xmlns:xsi="[Link]
instance" xsi:type="ns2:cargaisonAerienne">
<reference>CA1</reference>
<distance>700</distance>
<dateLivraison>2012-11-12T[Link]Z</dateLivraison>
<poidsMax>500.0</poidsMax>
</return>
<return xmlns:xsi="[Link]
instance" xsi:type="ns2:cargaisonRoutiere">
<reference>CR1</reference>
<distance>900</distance>
<dateLivraison>2012-11-11T[Link]Z</dateLivraison>
<temperatureConservation>22.0</temperatureConservation>
</return>
</ns2:getAllCargaisonsResponse>
</soap:Body>
</soap:Envelope>
med@youssfi.
Requête SOAP pour consulter toutes les
marchandises d’une cargaison
<SOAP-ENV:Envelope xmlns:SOAP-ENV="[Link]
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<getMarchParCarg xmlns="[Link]
<refCarg xmlns="">CA1</refCarg>
</getMarchParCarg>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<soap:Envelope xmlns:soap="[Link]
<soap:Body>
<ns2:getMarchParCargResponse xmlns:ns2="[Link]
<return>
<cargaison xmlns:xsi="[Link]
xsi:type="ns2:cargaisonAerienne">
<reference>CA1</reference>
<distance>700</distance>
<dateLivraison>2012-11-12T[Link]Z</dateLivraison>
<poidsMax>500.0</poidsMax>
</cargaison>
<nom>PC</nom>
<numero>1</numero>
<poids>22.0</poids>
<volume>66.0</volume>
</return>
<return> …… </return>
</ns2:getMarchParCargResponse>
</soap:Body>
</soap:Envelope>
med@youssfi.
Web Service REST FULL
package [Link];import [Link]; import
[Link]; import [Link].*; import [Link].*;
import [Link]; import
[Link].*; @Stateless
@Path("/transport")
public class TransportRESTService {
// Injection des dépendances
@EJB
private ITransportLocal metier;
// Méthode pour ajouter une cargaison
routière @GET
@Path("addCargRoutiere/{ref}/{dist}/{dateLiv}/{temp}")
@Produces(MediaType.APPLICATION_JSON)
public void ajouterCargaisonRoutiere(
@PathParam(value="ref")String ref, @PathParam(value="dist")int
dist,
@PathParam(value="dateLiv")Date dateLiv,
@PathParam(value="temp")float temp){
CargaisonRoutiere cr=new CargaisonRoutiere(ref, dist, dateLiv, temp);
[Link](cr);
} med@[Link]
Web Service SOAP
// Méthode pour ajouter une cargaison
Aérienne @GET
@Path("addCargAerienne/{ref}/{dist}/{dateLiv}/{poids}")
@Produces(MediaType.APPLICATION_JSON)
public void ajouterCargaisonAerienne(
@PathParam(value="ref")String ref, @PathParam(value="dist")int dist,
@PathParam(value="dateLiv")Date dateLiv, @PathParam(value="poids")float poids){
CargaisonAerienne ca=new CargaisonAerienne(ref, dist, dateLiv, poids);
[Link](ca);
}
// Méthode pour ajouter une
marchandise @GET
@Path("addMarch/{nom}/{poids}/{volume}/
{refCag}")
@Produces(MediaType.APPLICATION_JSON)
public void ajouterMarchandise(
@PathParam(value="nom")String nom, @PathParam(value="poids")double poids,
@PathParam(value="volume")double volume, @PathParam(value="refCarg")String
refCarg){ Marchandise m=new Marchandise(nom, poids, volume);
[Link](m, refCarg);
}
med@[Link]
Web Service SOAP
// Méthode pour consulter toutes les
cargaisons @GET
@Path("allCarg")
@Produces(MediaType.APPLICATION_JSON)
public List<Cargaison>
getAllCargaisons(){
return [Link]();
}
// Méthode pour consulter les marchandises d’une
cargaison @GET
@Path("marchandises/{refCarg}")
@Produces(MediaType.APPLICATION_JSON)
public List<Marchandise>
getMarchParCarg( @PathParam(value="refC
arg")String refCarg){
return [Link](refCarg);
}
med@[Link]
Web Service SOAP
// Méthode pour consulter une
cargaison @GET
@Path("consulterCargaison/
{refCarg}")
@Produces(MediaType.APPLICATION_J
SON) public Cargaison
consulterCargaison(
@PathParam(value="refCarg")String
refCarg){ return
[Link](refCarg);
}
// Méthode pour supprimer une
marchandise @GET
@Path("supprimerMarch/{num}")
@Produces(MediaType.APPLICATION_JSO
N) public void supprimerMarchandise(
@PathParam(value="num")Long numero){
[Link](numero);
}
}
med@[Link]
Application REST FULL
package [Link];
import
[Link];
import
[Link];
@ApplicationPath("/")
public class TransportRestApp extends Application {
}
med@[Link]
Tester le service REST
med@[Link]
Client Java, JSP Via un Proxy
SOAP
Créer un Projet Web Dynamique
med@[Link]
Générer un Proxy pour l’accès
au service SOAP
Créer un client Web Service
med@youssfi.
Générer un Proxy pour l’accès
au service SOAP
Spécifier l’adresse du WSDL
med@youssfi.
Générer un Proxy pour l’accès
au service SOAP
L’assistant est prêt à générer le code dans le dossier
src
med@[Link]
Proxy Généré
med@[Link]
Client Java Lourd
package clientSOAP; import [Link]; import
[Link].*; import [Link].*;
public class ClientLourd {
public static void main(String[]
args) { try {
TransportSOAPServiceProxy stub=new TransportSOAPServiceProxy();
[Link]("CA4", 600, [Link](), 800);
[Link]("CR4", 200, [Link](), 22);
[Link]("Ordinateurs", 900, 56, "CA4");
Cargaison[] cargs=[Link]();
[Link]("---- Totes Les cargaison---");
for(Cargaison c:cargs){
[Link]([Link]()
+"--"+[Link]()+"--
"+[Link]().getSimpleName());
}
[Link]("--- Marchandises d'une cargaison ---");
Marchandise[] marchandises=[Link]("CA1");
for(Marchandise m:marchandises){
[Link]([Link]()+"--"+[Link]()+"--"+[Link]());
}} catch (RemoteException e) { [Link](); } } }
Exécution du client Lourd
---- Totes Les
cargaison--- CA1--700--
CargaisonAerienne CA2--
123--CargaisonAerienne
CA4--600--
CargaisonAerienne CR1--
900--CargaisonRoutiere
CR2--120--
CargaisonRoutiere CR4--
200--CargaisonRoutiere
--- Marchandises d'une cargaison
--- PC--22.0--66.0
Imprimantes--23.0--88.0
med@[Link]
Client Web JSP
<%@page import="[Link].*"%>
<%@page import="[Link]"%>
<%
TransportSOAPServiceProxy stub=new TransportSOAPServiceProxy();
Cargaison[]
cargs=[Link]();
Marchandise[] mdises=new Marchandise[0];
String refCarg=null;
if([Link]("action")!=null){
String
action=[Link]("action");
if([Link]("marchandises")){
refCarg=[Link]("refCarg");
mdises=[Link](refCarg);
}
}
%>
med@[Link]
Client Web JSP
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<form action="[Link]" method="get">
Cargaisons:
<select name="refCarg">
<option>------</option>
<% for(Cargaison c:cargs) {%>
<option value="<%=[Link]()%>"
<%if([Link]().equals(refCarg)){ %> selected="selected" <%} %> >
<%=[Link]()%>
</option>
<%} %>
</select>
<input type="submit" name="action" value="marchandises">
</form>
med@[Link]
Client Web JSP
<table border="1" width="80%">
<tr>
<th>Num</th><th>Nom</th><th>Poids</th><th>Volume</th>
</tr>
<% for(Marchandise m:mdises){%>
<tr>
<td><%=[Link]()%></td><td><%=[Link]()%></td><td>
<%=[Link]()%></td><td><%=[Link]() %></td>
</tr>
<%} %>
</table>
</body>
</html>
med@[Link]
Client Web Ajax JQuery
Créer un Projet Web Statique
Copier le framework Jquery :
◦ [Link]
med@[Link]
[Link]
<html>
<head>
<script language="javascript" src="jquery/[Link]"></script>
<script language="javascript" src="jquery/[Link]"></script>
<script language="javascript" src="jquery/[Link]"></script>
<link rel="stylesheet" type="text/css" href="jquery/[Link]" />
</head>
<body onload="chargerCarg()">
<div>
Cargaisons :
<table border="1" width="80%">
<thead>
<tr><th>REF CARG</th><th>DATE LIVRAISON</th>
<th>DISTANCE</th><th>Type</th><th>Poids Max</th><th>Temp Cons</th>
</tr>
</thead>
<tbody id="cargaisons">
</tbody>
</table>
med@[Link]
[Link]
<p></
p>
<table border="1" width="80%">
<thead>
<tr>
<th>Numéro</th><th>Nom</th><th>Poids</th><th>Volume</
th>
</tr>
</thead>
<tbody id="tableBody">
</tbody>
</table>
</div>
</body>
</html>
med@[Link]
Code Java Script avec Jquery : [Link]
function chargerCarg(){
$.getJSON('/TP_TRANSPORT/transport/consulterCarg',
function(data){ filieres=data;
for(i in data){
$tr=$("<tr>");
$lien=$("<a>").append(data[i]
['reference']).attr("href","javascript:chargerMarchan dises('"+data[i]
['reference']+"')");
$td=$("<td>").append($lien);$[Link]($td);
$td=$("<td>").append(data[i]['dateLivraison']); $[Link]($td);
$td=$("<td>").append(data[i]['distance']);
$[Link]($td); var type=(data[i]
['poidsMax']==null)?"Aérienne":"Routière";
$td=$("<td>").append(type); $[Link]($td);
$td=$("<td>").append(data[i]['poidsMax']); $[Link]($td);
$td=$("<td>").append(data[i]['temperatureConservation']); $[Link]($td);
$("#cargaisons").append($tr);
}
}
);
}
med@[Link]
Code Java Script avec Jquery : [Link]
function chargerMarchandises(refCarg){
$.getJSON('/TP_TRANSPORT/transport/
consulterMarchParCarg/'+refCarg, function(data){
filieres=data;
for(i in data)
{
$tr=$("<tr>");
$td=$("<td>").append(data[i]['numero']); $[Link]($td);
$td=$("<td>").append(data[i]['nom']); $[Link]($td);
$td=$("<td>").append(data[i]['poids']); $[Link]($td);
$td=$("<td>").append(data[i]['volume']); $[Link]($td);
$("#tableBody").html("");
$("#tableBody").append($tr);
}
}
);
}
med@[Link]
Aperçu du client JQuery
med@[Link]
JQuery
Les premiers « Frameworks »
JavaScript a été créé pour améliorer l’interactivité entre les
utilisateurs et les page HTML.
Avec une grande maitrise de JavaScript, associé au CSS, on
peut créer des interfaces graphique web performantes de
très grande qualité.
Les développeurs professionnels JavaScript ont capitalisé
leurs expériences en créant des bibliothèques JavaScript qui
permettent de faciliter la tâche aux développeurs web.
Beaucoup de « Frameworks » JavaScript, on vu leurs
naissances :
◦ PrototypeJS : [Link]
◦ Mootools : [Link]
◦ DoJo Toolkit : [Link]
◦ Yahoo UI : [Link]/yui/
◦ ExtJS : [Link]
◦ UIZE : [Link]
◦ Spry : [Link]
◦ JQuery
med@[Link] 316
JQuery
Une bibliothèque javascript open-source
Elle permet de traverser et manipuler très
facilement l'arbre DOM des pages web à
l'aide d'une syntaxe simplifiée.
JQuery permet par exemple
◦ de changer/ajouter une classe CSS,
◦ créer des animations,
◦ Afficher des widgets (Menus, Panneaux à onglets etc..)
◦ modifier des attributs,
◦ Gérer les événements javascript
◦ Envoyer des requêtes HTTP AJAX aux serveurs Web
◦ ….
med@[Link] 317
une simple bibliothèque à
importer
Disponible sur le site de Jquery
[Link]
<script src="[Link]"></script>
Ou directement sur Google code
<script type="text/javascript" src=
"[Link]
</script>
med@[Link] 318
JavaScript / jQuery
Masquer tous les div du
document HTML avec JavaScript
pur:
divs =
[Link]('div');
for (i = 0; i < [Link]; i++)
{ divs[i].[Link] = 'none';
}
Faire la même chose avec jQuery :
$("div").hide();
med@[Link] 319
La fonction jQuery()
jQuery repose sur une seule
fonction : jQuery() ou $().
C’est une fonction JavaScript
Elle accepte des paramètres
Elle retourne un objet
$ : Syntaxe issue du framework
« Prototype »
med@[Link] 320
Les sélecteurs d’éléments: $
('anything')
$ accepte des ID :
◦ $('#nomID') retourne un élément sachant sont id
◦ Equivalent javascript :
[Link]('nomID')
$ accepte des classes css :
◦ $('.nomClasse') : retourne tous les éléments qui
correspondent à cette classe
◦ Equivalent javascript :
[Link]('nomClasse')
$ accepte plusieurs sélecteurs
◦ $('#article, .nouvelles, a')
◦ Permet de sélectionner les éléments suivants:
L’élément dont id est article
les éléments ayant la classe css nouvelles
Les liens hypertexte (a)
med@[Link] 321
Les sélecteurs d’éléments: $
('anything')
$(document)
◦ Extension de l'objet document à la classe jQuery.
$('*')
◦ Sélectionne tous les éléments.
$('#monDiv')
◦ Sélectionne l'élément ayant l'ID "monDiv".
$('[Link]')
◦ Sélectionne les éléments <p> ayant la classe
"first".
$('p[title]')
◦ Sélectionne les éléments <p> ayant un attribut
"title".
med@[Link] 322
Les sélecteurs d’éléments: $
('anything')
$('p[title="Bonjour"]')
◦ Sélectionne les éléments <p> dont l'attribut title
est "Bonjour".
$('p[title!="Bonjour"]')
◦ Sélectionne les éléments <p> dont l'attribut
title n'est pas "Bonjour".
$('p[title^="H"]')
◦ Sélectionne les éléments dont l'attribut title
commence par "H".
$('p[title$="H"]')
◦ Sélectionne les éléments dont l'attribut title fini par
"H".
med@[Link] 323
Les sélecteurs d’éléments: $
('anything')
$('p[title*="H"]')
◦Sélectionne les éléments dont
l'attribut title contient "H".
$('ul, ol, dl')
◦Sélectionne les éléments <ul>, <ol> et
<dl>
$('div .desc')
◦Sélectionne les éléments ayant la
classe "desc" descendants (au sens
CSS) d'éléments <div>.
med@[Link] 324
Les sélecteurs d’éléments: $
('anything')
$('div > .enfant')
◦ Sélectionne les éléments ayant la classe
"enfant" enfants d'éléments <div>.
$('label + input')
◦ Sélectionne les éléments <input /> dont l'élément
précédent (dans le DOM) est <label>.
$('#debut ~ div')
◦ Sélectionne les éléments <div> frères se situant
après l'élément dont l'id est "debut".
med@[Link] 325
Filtrer les sélections
jQuery offre une très large
possibilité de sélection
d'éléments en fonction de filtres
sur des collections d'éléments.
Le fonctionnement de la
sélection par filtre est simple : on
sélectionne d'abord un ensemble
d'éléments (par défaut, tous) puis
on affine cette sélection à partir
de certains critères.
med@[Link] 326
Filtrer les sélections
$('div:first')
◦ Sélectionne le premier élément <div>.
$('div:last')
◦ Sélectionne le dernier élément <div>.
$('div:not(.ok)')
◦ Sélectionne les <div> n'ayant pas la classe "ok".
$('div:[even|odd]')
◦ Sélectionne les éléments <div> de rang [pair|
impair] (le premier rang est 0).
$('div:[eq|lt|gt](n)')
◦ Sélectionne le ou les éléments
<div> de rang [égal|inférieur|
supérieur] à n.
med@[Link] 327
Filtrer les sélections
$(':header')
◦ Sélectionne les éléments <hn>.
$(':animated')
◦ Sélectionne les éléments actuellement animés.
$("div:contains('dvp')")
◦ Sélectionne les éléments <div> contenant le
texte "dvp" (sensible à la casse !)
$('div:empty')
◦ Sélectionne les éléments <div> vides.
$('div:has(p)')
◦ Sélectionne les éléments <div> ayant un descendant
<p>.
med@[Link] 328
Filtrer les sélections
$('div:parent')
◦ Sélectionne les éléments <div> ayant des enfants.
$('div:nth-child([n|even|odd|
equation])')
◦ // Les enfants de <div> [de rang n|pairs|impairs|
résultat de].
$('div:[first-child|last-child]')
◦ Les éléments [premier|dernier] enfants d'un élément
<div>.
$('div:only-child')
◦ Les éléments qui sont les seuls enfants d'un élément
<div>.
med@[Link] 329
Les éléments de formulaires
$(':input')
◦ Tous les éléments <input />, <textarea>, <select> et
<button>.
$(':[text|password|radio|checkbox|submit|imag
e|reset|button|file|hidden]')
◦ Les <input> du type choisi.
$(':[enabled|disabled|checked|selected]')
◦ Les <input /> possédant l'attribut indiqué.
med@[Link] 330
Exemple
<html>
<script type="text/javascript"
src="[Link]">
</script>
<body>
<div id="monDiv">Bonjour</div>
<a href="#" onClick="$('#monDiv').hide();">
disparition</a>
</body>
</html>
med@[Link] 331
Méthodes de l’objet jQuery
Lesméthodes s'appliquent généralement à tous
les éléments sélectionnés
◦ $('.classe').hide(); $('.classe').show();
◦ $('.classe').slideUp();$('.classe').slideDown();
med@[Link] 334
Utilisation des sélecteurs et
des événements
Au chargement document html :
$(document).ready (
function(){
// Code à exécuter au chargement de la page
}
);
Ou encore :
$(
function(){
// Code à exécuter au chargement de la page
}
);
med@[Link] 335
Exemple 2:
$(document).ready( function()
{
$("#valider").click( function()
{
$("#form").submit();
}
);
}
);
med@[Link] 339
Structure d’un accordéon
jQuery
Structure d’un accordellon JQuery (Code HTML)
<div id="accordeon">
<h3>Section1</h3>
<div>Contenu Section 1</div>
<h3>Section2</h3>
<div>Contenu Section 2</div>
<h3>Section3</h3>
<div>Contenu Section 3</div>
</div>
Comportement de l’accordéon (Code Java Scrit) :
<script language="javascript">
$(function(){
$("#accordeon").accordion();
})
</script>
Pour Que la section 2 soit active au début au lieu de la première :
$("#accordeon").accordion({active:1});
med@[Link] 340
Code Complet de la page
<html>
<head>
<title>Accordéon JQuery</title>
<script type="text/javascript" src="[Link]"></script>
<script type="text/javascript" src="[Link]"></script>
<link rel="stylesheet" type="text/css" href="[Link]" />
</head>
<body>
<div id="accordeon">
<h3>Section1</h3>
<div>Contenu Section 1</div>
<h3>Section2</h3>
<div>Contenu Section 2</div>
<h3>Section3</h3>
<div>Contenu Section 3</div>
</div>
<script language="javascript">
$(function(){
$("#accordeon").accordion();
})
</script>
</body>
</html>
med@[Link] 341
Une autre manière pour créer
l’accordéon
Structure d’un accordellon JQuery (Code HTML)
<ul id="accordeon2">
<li class="titre">Section 1</li>
<li>Contenu de la section 1</li>
Comportement : (JavaScript)
<script language="javascript">
$(function(){
$("#tabs").tabs());
})
</script>
med@[Link] 344
Menu déroulant
Structure : (HTML)
<ul id="menu">
<li class="ui-state-disabled"><a href="#">XML</a></li>
<li><a href="#">HTML</a></li>
<li><a href="#">CSS</a></li>
<li><a href="#">Java SCript</a></li>
<li><a href="#">Programmation</a>
<ul>
<li class="ui-state-disabled"><a href="#">Ada</
a></
<li><a href="#">Java</a></li>
<li><a href="#">C++</a></li>
</ul>
</li>
<li><a href="#">Multimédia</a></li>
</ul>
Comportement : (JavaScript)
<script language="javascript">
$(function(){
$( "#menu" ).menu();
})
</script>
med@[Link] 345
DatePicker : Calendrier
med@[Link] 346
DatePicker
<html>
<head>
<title>Date Picker</title>
<script type="text/javascript" src="[Link]"></script>
<script type="text/javascript" src="[Link]"></script>
<link rel="stylesheet" type="text/css" href="[Link]" />
</head>
<body>
<script>
$(function() {
$( "#dateDepart").datepicker();
});
</script>
Date:<input type="text" name="date" id="dateDepart" />
</body>
</html>
med@[Link] 347
Autocomplete
L'autocomplétion est un widget qui était déjà présent dans
la version 1.6 de jQuery UI, mais qui avait été retiré dans la
version suivante, la 1.7.
Pour la version 1.8, les développeurs de la librairie se sont
penchés dessus et l'ont amélioré, permettant ainsi de le
proposer de nouveau en libre téléchargement.
Traditionnellement, ce plugin est utilisé dans les champs
de recherche, mais vous pouvez tout aussi bien
l'implémenter dans une suggestion de pseudonyme ou
de prénom, par exemple.
med@[Link] 348
Autocomplete
Code HTML :
<div class="ui-widget">
<form>
Tags: <input type="text" id="recherche" />
</form>
</div>
Code Java Script :
<script>
$(function() {
var liste= [
"ActionScript","AppleScript","Asp","BASIC","C",
"C++","Clojure","COBOL","ColdFusion","Erlang",
"Fortran","Groovy","Haskell","Java","JavaScript",
"Lisp","Perl","PHP","Python","Ruby","Scala","Scheme"
];
$( "#recherche"
).autocomplete({ source: liste
});
});
</script>
med@youssfi. 349
net
Autocomplete : Paramètres
Spécification d'une longueur minimum
◦ Il existe une option qui permet d'exiger une longueur
minimum concernant la chaîne de caractère tapée par
l'utilisateur. En effet, par défaut, ce paramètre est
défini à 1.
$('#recherche').autocomplete({
source : [...],
/* on inscrit la liste de suggestions*/
minLength : 3
/* on indique qu'il faut taper au moins 3
caractères pour afficher l'autocomplétion*/
});
med@[Link] 350
Autocomplete : Paramètres
Retour sur l'option « source »
◦ La liste des paramètres pouvant être
définis peut être allongée indéfiniment,
mais on utilisera, en général, la syntaxe
suivante :
value, qui permet d'indiquer la valeur à inscrire dans le
champ de texte une fois sélectionnée ;
label, qui désigne en fait le titre de la suggestion ;
desc, qui donne la possibilité de spécifier une
description à chaque proposition ;
icon, qui devra prendre une image pour valeur.
med@[Link] 351
Autocomplete : Paramètres
Exemple :
$(function(){
var liste = [
{ value : 'Draggable', label : 'Draggable', desc :
'L\'interaction Draggable permet de déplacer un élément.' },
{ value : 'Droppable', label : 'Droppable', desc :
'L\'interaction Droppable permet de recevoir un élément.' },
{ value : 'Resizable', label : 'Resizable', desc :
'L\'interaction Resizable permet de redimensionner un
élément.' }
];
$('#recherche').autocomplete({
source : liste,
select : function(event, ui){
/* lors de la sélection d'une proposition */
$('#description').append( [Link] );
/* on ajoute la description de l'objet dans un bloc */
}
});
med@[Link] 352
Autocomplete : Paramètres
l'option « position »
◦ Par défaut, la liste de suggestions se place en dessous
du champ de texte qui lui est associé.
◦ Il se peut que ça ne vous convienne pas, et comme le mot
d'ordre de la librairie est toujours « flexibilité », vous
pouvez définir une nouvelle position grâce à un
paramètre.
◦ Le paramètre position prend pour valeur un objet,
contenant les positions suivantes :
my, qui définit la position de la liste autour du champ de texte ;
at, qui définit la position de la liste dans le champ de texte ;
◦ Exemple :
$('#recherche').autocomplete({
source : [...],
position : {
my : 'bottom',
at : 'top'
} /* ici, ma liste se placera au-dessus et à l'extérieur de
champ de texte.*/ mon
});
med@[Link] 353
Barre de progression
La barre de progression fonctionne grâce à un bloc div,
dans lequel s’implantera un deuxième bloc possédant
une largeur variable, qui fera donc office de progression.
Bien sûr, cela fonctionne en interne, grâce à la librairie, ce
qui nous permet de n'avoir qu'un seul bloc à déclarer.
Code JavaScript :
◦ $('#barre').progressbar();
Le plugin possède un paramètre value, et permet
d'indiquer la valeur de progression, en pour cents (0-
100%).
◦ $('#barre').progressbar({
◦ value : 50 // remplit 50% (la moitié) de la barre
◦ });
med@[Link] 35
Boites de dialogue
<div id="dialog" title="Boîte de dialogue de base">
Cette boîte de dialogue peut être redimensionnée, déplacée et
fermée.
</div>
<script>
$(function() {
$( "#dialog" ).dialog({width:300,height:200});
</script>
modal
positio
n
l'accès à la page). La valeur par défaut est false.
Position de la boîte de dialogue sur la page (elle est centrée par
Hauteur et
largeur de la défaut). Z-index de la boîte de dialogue (1000 par défaut).
boîte de Un ou plusieurs boutons affichés dans la boîte de dialogue.
dialogue à med@[Link] 355
l'ouverture.
Initi
alis
éà
tru
e,
ren
d la
boît
e de
dial
ogu
e
mo
dal
e
(c'e
st-
à-
dire
inte
rdit
Boites de dialogue
<script>
$(function() {
$( "#dialog" ).dialog({
modal: true,
buttons: {
"Oui": function() {
$('body').css('background', 'yellow');
$( this ).dialog( "close" );
},
"Non": function() {
$( this ).dialog( "close" );
}
}
});
});
</script>
med@[Link] 356
Interactions:
• Selectable :
JavaScript
<script>
$(function() {
$( "#selectable" ).selectable();
});
</script>
• Sortable:
JavaScript
$(function() {
$( "#sortable" ).sortable();
$( "#sortable" ).disableSelection();
});
med@[Link] 357
Interactions:
• Resizable :
JavaScript :
$( "#resizable" ).resizable();
• Draggable :
JavaScript :
$( "#draggable" ).draggable();
• Dropable :
JavaScript :
$( "#dropable" ).dropable();
med@[Link] 358
Interaction : Sotable
Code JavaScript :
<script>
$(function() {
$( "#sortable" ).sortable();
});
</script>
med@[Link] 359
Interaction : Dragable
Code JavaScript :
<script>
$(function() {
$( "#draggable" ).draggable();
});
</script>
med@[Link] 360
Animation : Exemple
<div id="contenu">
<h3>Titre</h3>
<p>Contenu</p>
</div>
<script>
$(function() {
$('#contenu').show('explode');
$('#contenu').show('slide');
$('#contenu').show('fold');
});
</script>
med@[Link] 361
Animation des couleurs
vouspourrez animer la couleur des éléments ! Les
propriétés sur lesquelles vous pouvez agir sont les
suivantes : backgroundColor
◦ borderBottomColor
◦ borderLeftColor
◦ borderRightColor
◦ borderTopColor
◦ color
◦ outlineColor
La syntaxe de la méthode animate() ne change pas
:
$('sel').animate({ prop1: val1, prop2: val2 }, durée,
modèle, function() {
//Une ou plusieurs instructions
});
med@[Link] 362
Exemple d’animation des
couleurs
- Code HTML : - Code JavaScript :
<div id="contenu"> $(function() {
$('#contenu').toggle(
<h3>Titre</h3>
function() {
<p>Contenu Contenu Contenu
$('#contenu').animate({
Contenu Contenu Contenu</p>
backgroundColor: '#fff',
</div>
color: 'red',
- Code CSS : left: '+=200',
#contenu { width: 500
border: 4px gray solid; }, 1000 );
background-color: #aaeae1; },
color: black; width: function() {
100px; position: relative; $('#contenu').animate({
backgroundColor: '#aaeae1',
}
color: 'black',
#contenu h3{
left: '-=200',
margin: 0; padding:
width: 100
0.4em; text-align: }, 1000 );
center; background-color: }
#777; ); });
}
med@[Link] 363
AJAX
Principe de base HTTP
Client Serveur
Requête
HTTP HTTP Web SGBD
Moteur PHP
Java Réponse
Script [Link]
HTTP HTML
ou XML
Qu'est ce qu'AJAX ?
open("méthode","url",flag):
◦Ouvre la connexion avec le serveur.
méthode -> "GET" ou "POST"
url -> l'url à laquelle on va envoyer notre
requête.
Si la méthode est GET, on met les paramètres dans
l'url.
flag -> true si l'on veut un dialogue asynchrone,
sinon, false
Propriétés et méthode de l’objet xhr
setRequestHeader("nom","valeur"):
◦ Assigne une valeur à un header HTTP qui sera
envoyé lors de la requête.
◦ Par exemple, pour un POST :
nom -> "Content-Type"
valeur -> "text/xml"
Propriétés et méthode de l’objet xhr
send("params"):
◦ Envoi la requête au serveur.
◦ Si la méthode est GET, on met null en paramètre.
◦ Si la méthode est POST, on met les paramètres a
envoyer, sous la forme :
"nomparam1=valeur1&nomparam2=valeur2".
abort()
: Abandonne la requête.
onreadystatechange :
◦ Ici, on va lui affecter notre fonction java script qui
sera exécutée à chaque "changement d'état" de
notre objet.
Propriétés et méthode de l’objet xhr
readyState :
◦ C'est cette propriété qu'on va tester
dans le onreadystatechange.
◦ Elle représente l'état de l'objet et peut
prendre plusieurs valeurs :
0 -> Non initialisé.
1 -> Ouverture (open() vient de s'exécuter).
2 -> Envoyé (send() vient de s'exécuter).
3 -> En cours (des données sont en train d'arriver).
4 -> Prêt (toutes les données sont chargées).
Propriétés et méthode de l’objet xhr
status :
◦ Le code de la réponse du serveur.
200 -> OK.
404 -> Page non trouvée.
...
statusText : Le message associé à status.
responseText : La réponse
retournée par le serveur, au format
texte.
responseXML: La réponse
retournée par le serveur, au format
dom XML.
Application AJAX PHP
On souhaite créer une application web, utilisant ajax et JSP,
qui permet de présenter un catalogue de produits en ligne.
Chaque produit appartient à une catégorie.
On considère une base de données MYSQL nommée «
Catalogue » qui contient deux tables :
◦ CATEGORIES (ID_CAT, NOM_CAT)
◦ PRODUITS (ID_PROD,NOM_PROD, PRIX, #ID_CAT)
L’application que l’on souhaite créer doit permettre :
◦ Au chargement, afficher toutes les catégories dans une zone de liste
◦ En sélectionnant une catégorie, afficher les produits de cette
catégorie dans un tableau.
Première solution Ajax avec HTML
ts [Link]: php
GET/[Link]
divProds [Link]
Rep HTTP : Liste HTML
p
[Link]:
GET/[Link]?
idc=2 AddProduit.p
hp
htm
CATEGORIE
SGBD S PRODUITS
[Link]
[Link]
<html>
<head>
<script language="javascript" src="[Link]">
</script>
</head>
<body onload="chargerCategories()">
Catégories:
<div id="cats" style="display:inline"></div>
<hr/>
Produits
:
<div id="prods"></div>
</body>
</html>
[Link]
// JavaScript Document
function getXhr(){
var xhr = null;
if([Link]
t)
// Firefox et autres
xhr = new XMLHttpRequest();
else
if([Link]){
// Internet Explorer
try {
xhr = new ActiveXObject("[Link]");}
catch (e) { xhr = new ActiveXObject("[Link]");
}
} else {
// XMLHttpRequest non supporté par le navigateur
alert("Le navigateur ne supporte pas les objets
XMLHTTPRequest...");
xhr = false; }
return xhr;
}
[Link] (communication synchrone)
function chargerCategories()
{ var xhr=getXhr();
[Link]("POST","[Link]",false);
[Link]("");
var rep=[Link];
[Link]("cat").innerHTML=rep;
}
function chargerProduits(idc)
{ var xhr=getXhr();
[Link]("GET","[Link]?
cat="+idc,false); [Link](null);
var rep=[Link];
[Link]("prod").innerHTML=rep;
}
[Link] (communication asynchrone)
function chargerCategories(){
var xhr=getXhr();
[Link]("GET","[Link]",tru
e);
[Link]=function(){
if(([Link]==4)&&([Link]==200)){
var rep=[Link];
[Link]("cat").innerHTML=rep;
}
}
[Link](null);
}
function
chargerProduits(idc){ var
xhr=getXhr();
[Link]("GET","[Link]?cat="+idc,true);
[Link]=function(){
if(([Link]==4)&&([Link]==200)){
var rep=[Link];
[Link]("prod").innerHTML=rep;
}
}
[Link](null);
}
Ajax avec JQuery : [Link]
$(document).ready(function(){// Au chargement du document
chargerCategories(); // Faire appel à la fonction chargerCategories()
});
function chargerCategories(){
// Envoyer une requête Ajax avec la méthode GET au script [Link]
$.ajax({
url:'[Link]',type:'GET',dataType:'html',
success:function(reponse,status){ // En cas de succès
$("#cats").html(reponse); // Afficher la réponse dans le div cats
$("#cat").change(function(){chargerProduits($(this).val())});
/* En modifiant la valeur de la liste, faire appel à la fonction
chargerProduits(valeur de idCat sélectionnée) */
}
});
}
function chargerProduits(idc){
$.ajax({
url:'[Link]',type:'GET',dataType:'html',data:'cat='+i
dc, success:function(reponse,status){
$("#prods").html(reponse);
},
error:function(resultat,status,erreur){ // En cas d’erreur
$("#prods").html(erreur); // Afficher l’erreur
}
});
}
Ajax avec JQuery : les fonctions get() et post() de JQuery
$(document).ready(function(){
chargerCategories();
});
function chargerCategories(){
$.get('[Link]',function(reponse){
$("#cats").html(reponse);
$("#cat").change(function(){chargerProduits($
(this).val())});
}
);
}
function chargerProduits(idc){
$.get('[Link]','cat='+idc,function(reponse){
$("#prods").html(reponse);
}
);
}
JQuery et JSON
Application : Consulter les produits par catégorie
[Link]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
Transitional//EN"
"[Link]
[Link]">
<html xmlns="[Link]
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"
/>
<title>TP Ajax</title>
<script language="javascript" src="[Link]"></script>
<script language="javascript" src="[Link]"></script>
<script language="javascript"
src="[Link]"></script>
<link rel="stylesheet" type="text/css" href="[Link]" />
</head>
<body>
Catégries:<div id="cats" style="display:inline"></div>
<div id="prods"></div>
</body>
</html>
[Link]
$(document).ready(function(){
chargerCategories();
});
function chargerCategories(){
$.getJSON('[Link]',
med@[Link]