I. Introduction▲
Ce court article traite de l'écriture de Web Services (SOAP) en Java. Nous verrons qu'il est très facile de créer ses premiers Web Services à l'aide de JAX-WS, en suivant quelques étapes simples.
On parle aussi de Web Services étendus qui s'appuient sur des standards, des piles spécifiques pour la sécurité et l'interopérabilité, et qui sont particulièrement adaptés à la manipulation de services.
Dans le passé, les développeurs utilisaient des bibliothèques, comme Axis ou Xfire, avec plus ou moins de peines (processus complexes, générations longues, synchronisations et déploiements pénibles, performances douteuses, etc.). Heureusement, les nouvelles API, avec JAX-WS en tête, changent la donne.
Dans ce tutoriel, nous allons utiliser l'implémentation de référence « JAX-WS RT » (aussi connue sous le nom « Metro ») de JAX-WS, pour exposer via des Web Services les fonctionnalités de notre application Web fictive. Nous utiliserons le logiciel SoapUI pour vérifier que tout fonctionne.
Dans un prochain article, je m'intéresserai aux Web Services REST, qui entrainent l'utilisation d'autres concepts et mécanismes. Je n'en parlerai donc pas ici.
I-A. À propos▲
Découvrir une technologie n'est pas chose facile. En aborder plusieurs d'un coup l'est encore moins. Partant de ce constat, cet article a été écrit pour aller à l'essentiel. Les points importants sont présentés dans le corps de l'article et les éléments secondaires sont expliqués en annexes.
I-B. Avant de commencer▲
Pour écrire ce tutoriel, j'ai utilisé les éléments suivants :
- Java JDK 1.6.0_24-b07 ;
- Eclipse Indigo 3.7 JEE 64b ;
- Maven 3.0.3 ;
- Tomcat 6.0.29 64b ;
- Pretty Faces 3.3.2 ;
- JAX-WS RT 2.2.5.
II. Découverte du projet d'exemple▲
II-A. Télécharger, installer et importer le projet d'exemple▲
Pour commencer, je vous propose de télécharger le fichier Zip « fibowebapp2.zip », contenant un projet Java-Maven d'exemple (une miniwebapp) qui va nous servir de support pour les fonctionnalités présentées dans la suite de cet article.
Compilez le projet d'exemple et importez-le dans Eclipse (comme expliqué dans le tutoriel « Importer un projet Maven dans Eclipse en 5 minutes ») ou dans l'IDE de votre choix.
Installez ensuite la webapp dans le serveur d'application de votre choix, par exemple Tomcat 6, ce que vous pouvez faire directement depuis Eclipse.
Pour suivre ce tutoriel, vous pouvez vous contenter de lire les codes proposés ci-dessous (codes complets en annexes) et de faire confiance aux captures d'écran.
II-B. Ce que fait déjà le projet d'exemple▲
Le projet d'exemple est une petite webapp permettant de calculer plusieurs fonctions mathématiques célèbres. Cette application Web n'a rien de très complexe. Elle utilise le framework Web JSF, inclus dans JEE depuis la version 5. Les fonctionnalités (calcul de la suite de Fibonacci et du factoriel) servent uniquement d'illustration.
Comme on peut le constater sur la capture d'écran, la webapp calcule la valeur du membre de la suite de Fibonacci pour un rang donné. La Webapp calcule aussi les membres de rangs inférieurs, ce qui permet d'afficher une liste intéressante. En outre, la webapp utilise deux méthodes de calcul. La première met en œuvre un algorithme récursif lent, mais qui donne une valeur exacte. La seconde se sert d'une fonction mathématique rapide dont la justesse des résultats dépend de la précision des constantes internes utilisées. La dernière colonne du tableau de résultat fait apparaitre les erreurs d'approximation.
Cette petite Webapp a été présentée en détail dans l'article « De jolies URL dans vos applications Web JSF avec Pretty Faces ».
Pour réaliser le calcul, la Webapp utilise le service « FiboService » :
public
class
FiboService {
// singleton
private
static
FiboService instance;
public
static
synchronized
FiboService getInstance
(
) {
if
(
instance ==
null
) {
instance =
new
FiboService
(
);
}
return
instance;
}
// Calcul recursif mais exact
public
Long calculerFibonacci
(
Integer n) {
...
}
// Calcul direct, mais approximatif
public
Long calculerApproximationfibonacci
(
Integer n) {
...
}
...
Quant au bean « FiboBean » qui « manage » la page, il lance les appels qu'il faut pour remplir le bean de résultat « FiboResult » :
public
class
FiboResult {
private
Integer rang;
private
Long valeurExacte;
private
Long valeurApproximative;
private
Long approximation;
public
FiboResult
(
Integer rang, Long valeurExacte, Long valeurApproximative) {
this
.rang =
rang;
this
.valeurExacte =
valeurExacte;
this
.valeurApproximative =
valeurApproximative;
this
.approximation =
Math.abs
(
valeurExacte -
valeurApproximative);
}
...
public
class
FiboBean {
private
FiboService fiboService =
FiboService.getInstance
(
);
private
List<
FiboResult>
valeurs;
...
public
void
calculer
(
) {
valeurs =
new
ArrayList<
FiboResult>(
rang);
for
(
int
i =
1
; i <=
rang; i++
) {
final
FiboResult fiboResult =
calculerFiboResult
(
i);
valeurs.add
(
fiboResult);
}
Long valeur =
fiboService.calculerFibonacci
(
rang);
}
private
FiboResult calculerFiboResult
(
Integer rang) {
Long valeurExacte =
fiboService.calculerFibonacci
(
rang);
Long valeurApproximative =
fiboService.calculerApproximationfibonacci
(
rang);
FiboResult fiboResult =
new
FiboResult
(
rang, valeurExacte, valeurApproximative);
return
fiboResult;
}
...
III. Action▲
III-A. Maven▲
Durée estimée : 1 minute.
Pour utiliser JAX-WS (JAX-WS RT), il faut ajouter une dépendance dans le fichier « pom.xml ».
<!-- JAX-WS RT -->
<dependency>
<groupId>
com.sun.xml.ws</groupId>
<artifactId>
jaxws-rt</artifactId>
<version>
2.2.5</version>
</dependency>
Puis relancer une installation Maven.
mvn clean install eclipse:eclipse
En fonction des éléments déjà présents sur le disque dur, le résultat de l'installation Maven devrait ressembler à la trace suivante :
C:\...\fibowebapp>
mvn clean install eclipse:eclipse
[INFO] Scanning for
projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building fibowebapp 1
.0
-SNAPSHOT
[INFO] ------------------------------------------------------------------------
...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11
.025s
[INFO] Finished at: Thu Apr 30
20
:59
:22
CEST 2012
[INFO] Final Memory: 10M/53M
[INFO] ------------------------------------------------------------------------
On doit ensuite faire un refresh (touche F5) dans Eclipse pour faire apparaitre JAX-WS (et ses dépendances) dans la liste des bibliothèques référencées.
III-B. Création du Web service▲
Durée estimée : 1 minute.
Pour fabriquer un Web service avec JAX-WS, c'est relativement simple. Il suffit de créer un bean qu'on va annoter avec « @WebService ». Les méthodes « public » de ce bean seront nos services.
package
com.dvp.fibowebapp.ws;
import
javax.jws.WebService;
import
javax.jws.soap.SOAPBinding;
import
javax.jws.soap.SOAPBinding.Style;
@WebService
@SOAPBinding
(
style =
Style.RPC)
public
class
FibonacciWebService {
public
Long fibonacci
(
Integer rang) {
return
0
L;
}
}
Pour le moment, le bean est relativement simple. Il renvoie toujours zéro. Pour réaliser le calcul, on va s'inspirer de « FiboBean », présenté plus haut.
@WebService
@SOAPBinding
(
style =
Style.RPC)
public
class
FibonacciWebService {
private
final
FiboService fiboService =
FiboService.getInstance
(
);
public
Long fibonacci
(
Integer rang) {
Long result =
fiboService.calculerFibonacci
(
rang);
return
result;
}
Il faut maintenant « mapper » ce service. Pour cela, il faut créer le fichier « sun-jaxws.xml » dans le dossier « WEB-INF » de la webapp.
<?xml version="1.0" encoding="UTF-8"?>
<endpoints
xmlns
=
"http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version
=
"2.0"
>
<endpoint
name
=
"fibonacci"
implementation
=
"com.dvp.fibowebapp.ws.FibonacciWebService"
url-pattern
=
"/fibonacci"
/>
</endpoints>
Et bien entendu, il faut ajouter un filtre dans le « web.xml ». Pour utiliser JAX-WS, on peut utiliser simplement la servlet « WSServlet ».
...
<listener>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>
WSServlet</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>
1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>
WSServlet</servlet-name>
<url-pattern>
/fibonacci</url-pattern>
</servlet-mapping>
...
À ce stade, le Web service est prêt. Le serveur va générer le WSDL (le fichier qui décrit le service) à l'exécution. On peut le voir directement dans Firefox en demandant l'adresse « http://…/fibowebapp/fibonacci?wsdl ».
<?xml version='1.0' encoding='UTF-8'?>
<definitions
xmlns
:
wsu
=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns
:
wsp
=
"http://www.w3.org/ns/ws-policy"
xmlns
:
wsp1_2
=
"http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns
:
wsam
=
"http://www.w3.org/2007/05/addressing/metadata"
xmlns
:
soap
=
"http://schemas.xmlsoap.org/wsdl/soap/"
xmlns
:
tns
=
"http://ws.fibowebapp.dvp.com/"
xmlns
:
xsd
=
"http://www.w3.org/2001/XMLSchema"
xmlns
=
"http://schemas.xmlsoap.org/wsdl/"
targetNamespace
=
"http://ws.fibowebapp.dvp.com/"
name
=
"FibonacciWebServiceService"
>
<types />
<message
name
=
"fibonacci"
>
<part
name
=
"arg0"
type
=
"xsd:int"
/>
</message>
<message
name
=
"fibonacciResponse"
>
<part
name
=
"return"
type
=
"xsd:long"
/>
</message>
<portType
name
=
"FibonacciWebService"
>
<operation
name
=
"fibonacci"
>
<input
wsam
:
Action
=
"http://ws.fibowebapp.dvp.com/FibonacciWebService/fibonacciRequest"
message
=
"tns:fibonacci"
/>
<output
wsam
:
Action
=
"http://ws.fibowebapp.dvp.com/FibonacciWebService/fibonacciResponse"
message
=
"tns:fibonacciResponse"
/>
</operation>
</portType>
<binding
name
=
"FibonacciWebServicePortBinding"
type
=
"tns:FibonacciWebService"
>
<
soap
:
binding
transport
=
"http://schemas.xmlsoap.org/soap/http"
style
=
"rpc"
/>
<operation
name
=
"fibonacci"
>
<
soap
:
operation
soapAction
=
""
/>
<input>
<
soap
:
body
use
=
"literal"
namespace
=
"http://ws.fibowebapp.dvp.com/"
/>
</input>
<output>
<
soap
:
body
use
=
"literal"
namespace
=
"http://ws.fibowebapp.dvp.com/"
/>
</output>
</operation>
</binding>
<service
name
=
"FibonacciWebServiceService"
>
<port
name
=
"FibonacciWebServicePort"
binding
=
"tns:FibonacciWebServicePortBinding"
>
<
soap
:
address
location
=
"http://localhost:8080/fibowebapp/fibonacci"
/>
</port>
</service>
</definitions>
III-C. Tester le Web service▲
Durée estimée : 1 minute.
On va maintenant tester le Web service à l'aide du logiciel gratuit Soap UI.
Pour commencer, il faut créer un nouveau projet à l'aide du menu « File/New SoapUi project ». L'idéal est que le serveur soit démarré durant cette étape, pour que SoapUI puisse s'y connecter.
Le logiciel va chercher toutes les informations dans le WSDL et créer un premier jeu de test.
<
soapenv
:
Envelope
xmlns
:
soapenv
=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns
:
ws
=
"http://ws.fibowebapp.dvp.com/"
>
<
soapenv
:
Header/>
<
soapenv
:
Body>
<
ws
:
fibonacci>
<arg0>
?</arg0>
</
ws
:
fibonacci>
</
soapenv
:
Body>
</
soapenv
:
Envelope>
Pour vérifier que tout fonctionne, il suffit de remplacer les valeurs manquantes dans le XML (à gauche) et signalées par des points d'interrogation (?) puis de cliquer sur la flèche.
<
S
:
Envelope
xmlns
:
S
=
"http://schemas.xmlsoap.org/soap/envelope/"
>
<
S
:
Body>
<
ns2
:
fibonacciResponse
xmlns
:
ns2
=
"http://ws.fibowebapp.dvp.com/"
>
<return>
377</return>
</
ns2
:
fibonacciResponse>
</
S
:
Body>
</
S
:
Envelope>
Il y a tout de même un petit détail qui choque, c'est que le XML n'est pas très clair. En particulier, quand on indique le rang, il faut remplir la balise « arg0 ». Ici, ce n'est pas très compliqué, car il n'y a qu'un seul paramètre, mais il faut imaginer le cas où on en a plusieurs. Pour améliorer le Web service, on va simplement compléter la méthode de calcul avec l'annotation « @WebParam ».
@WebService
@SOAPBinding
(
style =
Style.RPC)
public
class
FibonacciWebService {
...
public
Long fibonacci
(
@WebParam
(
name =
"rang"
) Integer rang) {
...
On relance le serveur et on fait un « refresh » dans SoapUI pour avoir la nouvelle version du WSDL, avec des paramètres nommés.
<
soapenv
:
Envelope
xmlns
:
soapenv
=
"http://schemas.xmlsoap.org/soap/envelope/"
xmlns
:
ws
=
"http://ws.fibowebapp.dvp.com/"
>
<
soapenv
:
Header/>
<
soapenv
:
Body>
<
ws
:
fibonacci>
<rang>
?</rang>
</
ws
:
fibonacci>
</
soapenv
:
Body>
</
soapenv
:
Envelope>
III-D. Des retours plus complexes▲
Durée estimée : 1 minute.
On va maintenant ajouter une méthode de service qui renvoie une liste de résultats en utilisant les deux algorithmes présentés plus haut. La méthode renverra un tableau d'objets dont on spécifiera la taille dans l'appel (histoire d'avoir un second paramètre).
@WebService
@SOAPBinding
(
style =
Style.RPC)
public
class
FibonacciWebService {
...
public
FiboDTO[] fibonacciList
(
@WebParam
(
name =
"rang"
) Integer rang,
@WebParam
(
name =
"limit"
)Integer nb) {
... // code en annexe
}
...
Ici, je retourne des éléments de type « FiboDTO » et non de type « FiboResult ». J'ai pris l'habitude de créer des types spécifiques pour mes objets de retour et de paramètre de mes Web services afin de ne pas exposer mon métier directement. En plus de ne pas dévoiler le contenu de mon domaine, cela me permet d'écrire des objets légers. À titre d'illustration, on peut imaginer un Web service renvoyant le nom et le prénom d'un utilisateur. Je vais alors créer un bean ne contenant que ces deux informations, plutôt que de renvoyer la liste complète des informations (âge, adresse, etc.) dudit utilisateur.
public
class
FiboDTO {
private
Integer rang;
private
Long valeurExacte;
private
Long valeurApproximative;
private
Long approximation;
public
FiboDTO
(
) {
super
(
);
}
...
De nouveau, je relance le serveur et je rafraichis SoapUI. Mon nouveau service apparait dans la liste et je peux tester comme précédemment.
<
S
:
Envelope
xmlns
:
S
=
"http://schemas.xmlsoap.org/soap/envelope/"
>
<
S
:
Body>
<
ns2
:
fibonacciListResponse
xmlns
:
ns2
=
"http://ws.fibowebapp.dvp.com/"
>
<return>
<item>
<approximation>
1</approximation>
<rang>
63</rang>
<valeurApproximative>
6557470319843</valeurApproximative>
<valeurExacte>
6557470319842</valeurExacte>
</item>
<item>
<approximation>
1</approximation>
<rang>
62</rang>
<valeurApproximative>
4052739537882</valeurApproximative>
<valeurExacte>
4052739537881</valeurExacte>
</item>
<item>
<approximation>
0</approximation>
<rang>
61</rang>
<valeurApproximative>
2504730781961</valeurApproximative>
<valeurExacte>
2504730781961</valeurExacte>
</item>
...
</return>
</
ns2
:
fibonacciListResponse>
</
S
:
Body>
</
S
:
Envelope>
Et voilà…
IV. Conclusions▲
Comme on vient de le voir, c'est donc très simple et très rapide d'exposer (i.e. écrire) un Web Service à l'aide de JAX-WS. Nous n'avons abordé que les points-clés, mais cela devrait être suffisant pour bien débuter. Je vous recommande néanmoins la lecture des tutoriels Mickael Baron (cf. liens en annexes) à propos du SOA (Service Oriented Architecture) pour approfondir la question.
Le code final de ce tutoriel est disponible dans le fichier ZIP fibowebapp3.zip.code final
Vos retours nous aident à améliorer nos publications. N'hésitez donc pas à commenter cet article sur le forum : 13 commentaires
Retrouvez mes autres tutoriels rapides sur developpez.com à l'adresse https://thierry-leriche-dessirier.developpez.com/#page_articlesTutoriels
V. Remerciements▲
Je tiens à remercier, en tant qu'auteur du tutoriel, toutes les personnes qui m'ont aidé et soutenu. Je pense tout d'abord à mes collègues qui subissent mes questions au quotidien, mais aussi à mes contacts et amis du Web, dans le domaine de l'informatique ou non, qui m'ont fait part de leurs remarques et critiques. Bien entendu, je n'oublie pas l'équipe de developpez.com qui m'a guidé dans la rédaction de cet article et m'a aidé à le corriger et le faire évoluer, principalement sur le forum.
Plus particulièrement j'adresse mes remerciements à Mickael Baron (keulkeul), Claude Leloup, Robin56, Nemek et lunatix.
VI. Annexes▲
VI-A. Quelques définitions▲
Pour compléter cet article, voici quelques passages, issus de Wikipedia, à propos des éléments abordés.
Service Web : C'est « un programme informatique permettant la communication et l'échange de données entre applications et systèmes hétérogènes dans des environnements distribués. [..] Le concept a été précisé et mis en œuvre dans le cadre de Web Services Activity2, au W3C, particulièrement avec le protocole SOAP. [..] Le concept s'enrichit avec l'approfondissement des notions de ressource et d'état, dans le cadre du modèle REST, et l'approfondissement de la notion de service, avec le modèle SOA. Dans sa présentation la plus générale, un service Web se concrétise par un agent, réalisé selon une technologie informatique précise, par un fournisseur du service. Un demandeur, à l'aide d'un agent de requête, utilise ce service. Fournisseur et demandeur partagent une même sémantique du service Web, tandis qu'agent et agent de requête partagent une même description du service pour coordonner les messages qu'ils échangent. Il existe plusieurs technologies derrière le terme services Web : 1) les services Web de type REST (Representational state transfer) exposent entièrement ces fonctionnalités comme un ensemble de ressources (URI) identifiables et accessibles par la syntaxe et la sémantique du protocole HTTP. [..] ; 2) les Services Web WS-* exposent ces mêmes fonctionnalités sous la forme de services exécutables à distance. Leurs spécifications reposent sur les standards SOAP et WSDL pour transformer les problématiques d'intégration héritées du monde Middleware en objectif d'interopérabilité. »
SOAP : c'est « un protocole de RPC orienté objet bâti sur XML. Il permet la transmission de messages entre objets distants [..] Le transfert se fait le plus souvent à l'aide du protocole HTTP, mais peut également se faire par un autre protocole, comme SMTP. Le protocole SOAP est composé de deux parties : 1) une enveloppe, contenant des informations sur le message lui-même afin de permettre son acheminement et son traitement ; 2) un modèle de données, définissant le format du message, c'est-à-dire les informations à transmettre. »
VI-B. Liens▲
Je vous invite à lire plusieurs articles de Mickael Baron (dans la rubrique « Architectures Orientées Services (SOA) »), dont je me suis inspiré, sur des sujets connexes, à l'adresse : https://mbaron.developpez.com/#LV
Le logiciel SoapUI est téléchargeable à l'adresse http://www.soapui.org
Retrouvez mes autres tutoriels sur developpez.com à l'adresse https://thierry-leriche-dessirier.developpez.com/#page_articlesTutoriels
Ajoutez-moi à vos contacts à l'aide du QR Code suivant :
VI-C. Les fichiers importants en entier▲
package
com.dvp.fibowebapp;
import
java.util.HashMap;
import
java.util.Map;
public
class
FiboService {
private
final
static
double
NOMBRE_OR =
1.61803398874989
;
private
final
static
double
RACINE_5 =
2.236067977499
;
private
static
FiboService instance;
private
static
Map<
Integer, Long>
mapExact;
private
static
Map<
Integer, Long>
mapApproximation;
private
FiboService
(
) {
mapExact =
new
HashMap<
Integer, Long>(
);
mapApproximation =
new
HashMap<
Integer, Long>(
);
}
public
static
synchronized
FiboService getInstance
(
) {
if
(
instance ==
null
) {
instance =
new
FiboService
(
);
}
return
instance;
}
public
Long calculerFibonacci
(
Integer n) {
// REGLE RG024.4
if
(
n <=
0
) {
throw
new
IllegalArgumentException
(
"On ne calcule que pour des nombres positifs"
);
}
// REGLE RG024.1 : f(1) = 1
// REGLE RG024.2 : f(2) = 1
if
(
n ==
1
||
n ==
2
) {
return
1
L;
}
// REGLE RG024.5
// REGLE RG024.6
Long valeur =
mapExact.get
(
n);
if
(
valeur !=
null
) {
return
valeur;
}
// REGLE RG024.3.x : f(n) = f(n-1) + f(n-2)
valeur =
calculerFibonacci
(
n -
1
) +
calculerFibonacci
(
n -
2
);
mapExact.put
(
n, valeur);
return
valeur;
}
public
Long calculerApproximationfibonacci
(
Integer n) {
if
(
n <=
0
) {
throw
new
IllegalArgumentException
(
"On ne calcule que pour des nombres positifs"
);
}
if
(
n ==
1
||
n ==
2
) {
return
1
L;
}
Long valeur =
mapApproximation.get
(
n);
if
(
valeur !=
null
) {
return
valeur;
}
final
double
nominateur =
Math.pow
(
NOMBRE_OR, n);
final
double
result =
nominateur /
RACINE_5;
valeur =
Math.round
(
result);
mapApproximation.put
(
n, valeur);
return
valeur;
}
}
package
com.dvp.fibowebapp;
public
class
FiboResult {
private
Integer rang;
private
Long valeurExacte;
private
Long valeurApproximative;
private
Long approximation;
public
FiboResult
(
Integer rang, Long valeurExacte, Long valeurApproximative) {
super
(
);
this
.rang =
rang;
this
.valeurExacte =
valeurExacte;
this
.valeurApproximative =
valeurApproximative;
this
.approximation =
Math.abs
(
valeurExacte -
valeurApproximative);
}
/* hashcode / equals / tostring */
@Override
public
int
hashCode
(
) {
final
int
prime =
31
;
int
result =
1
;
result =
prime *
result +
((
rang ==
null
) ? 0
: rang.hashCode
(
));
return
result;
}
@Override
public
String toString
(
) {
return
"FiboResult [rang="
+
rang +
", valeurExacte="
+
valeurExacte +
", valeurApproximative="
+
valeurApproximative +
", approximation="
+
approximation +
"]"
;
}
@Override
public
boolean
equals
(
Object obj) {
if
(
this
==
obj)
return
true
;
if
(
obj ==
null
)
return
false
;
if
(
getClass
(
) !=
obj.getClass
(
))
return
false
;
FiboResult other =
(
FiboResult) obj;
if
(
rang ==
null
) {
if
(
other.rang !=
null
)
return
false
;
}
else
if
(!
rang.equals
(
other.rang))
return
false
;
return
true
;
}
/* Getter et setter */
public
Integer getRang
(
) {
return
rang;
}
public
Long getValeurExacte
(
) {
return
valeurExacte;
}
public
Long getValeurApproximative
(
) {
return
valeurApproximative;
}
public
Long getApproximation
(
) {
return
approximation;
}
}
package
com.dvp.fibowebapp;
import
java.util.ArrayList;
import
java.util.List;
import
javax.faces.bean.ManagedBean;
@ManagedBean
(
name =
"fiboBean"
)
public
class
FiboBean {
private
static
final
Integer DEFAULT_RANG =
7
;
private
Integer rang;
private
Long valeur;
private
List<
FiboResult>
valeurs;
private
final
FiboService fiboService =
FiboService.getInstance
(
);
public
void
calculer
(
) {
if
(
rang ==
null
) {
return
;
}
System.out.println
(
"Calcul de la suite de Fibonacci pour le rang "
+
rang);
// Je calcule d'abord la liste.
valeurs =
new
ArrayList<
FiboResult>(
rang);
for
(
int
i =
1
; i <=
rang; i++
) {
final
FiboResult fiboResult =
calculerFiboResult
(
i);
valeurs.add
(
fiboResult);
}
// Puis la valeur pour le rang. Ici j'aurais pu optimiser, mais ce n'est
// pas l'objet de cet article.
valeur =
fiboService.calculerFibonacci
(
rang);
}
private
FiboResult calculerFiboResult
(
Integer rang) {
final
Long valeurExacte =
fiboService.calculerFibonacci
(
rang);
final
Long valeurApproximative =
fiboService.calculerApproximationfibonacci
(
rang);
final
FiboResult fiboResult =
new
FiboResult
(
rang, valeurExacte, valeurApproximative);
return
fiboResult;
}
/* Getters et setters */
public
Integer getRang
(
) {
return
rang;
}
public
void
setRang
(
Integer rang) {
this
.rang =
rang;
}
public
Long getValeur
(
) {
return
valeur;
}
public
List<
FiboResult>
getValeurs
(
) {
return
valeurs;
}
public
Integer getDefaultRang
(
) {
return
DEFAULT_RANG;
}
public
List<
FiboResult>
getValeursInversees
(
) {
final
List<
FiboResult>
result =
new
ArrayList<
FiboResult>(
);
for
(
int
i =
valeurs.size
(
) -
1
; 0
<=
i; i--
) {
result.add
(
valeurs.get
(
i));
}
return
result;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns
=
"http://maven.apache.org/POM/4.0.0"
xmlns
:
xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi
:
schemaLocation
=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
>
<modelVersion>
4.0.0</modelVersion>
<groupId>
com.dvp</groupId>
<artifactId>
fibowebapp</artifactId>
<packaging>
war</packaging>
<version>
1.0-SNAPSHOT</version>
<name>
fibowebapp</name>
<description>
fibowebapp</description>
<licenses>
<license>
<name>
Copyright ©1995-2012 thierryler.com et Copyright ©2012 Developpez.com</name>
<comments>
Les sources présentées sur cette page sont libres de droits, ...</comments>
</license>
</licenses>
<developers>
<!-- Thierry -->
<developer>
<name>
Thierry Leriche-Dessirier</name>
<roles>
<role>
Developper</role>
</roles>
<organization>
ICAUDA</organization>
</developer>
</developers>
<properties>
<!-- Build -->
<project.build.sourceEncoding>
UTF-8</project.build.sourceEncoding>
<java.version>
1.6</java.version>
<wtp.version>
2.0</wtp.version>
<!-- Test -->
<junit.version>
4.10</junit.version>
<!-- Servlet et pages -->
<mojarra.version>
2.1.4</mojarra.version>
<jboss-el.version>
2.0.1.GA</jboss-el.version>
<jstl.version>
1.2</jstl.version>
<servlet-api.version>
2.5</servlet-api.version>
<!-- Plugins -->
<maven-compiler-plugin.version>
2.3.2</maven-compiler-plugin.version>
<maven-eclipse-plugin.version>
2.8</maven-eclipse-plugin.version>
<tomcat-maven-plugin.version>
1.1</tomcat-maven-plugin.version>
<!-- Pretty faces -->
<prettyfaces-jsf2.version>
3.3.2</prettyfaces-jsf2.version>
<!-- JAX WS RT -->
<jaxws-rt.version>
2.2.5</jaxws-rt.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- JSF -->
<dependency>
<groupId>
com.sun.faces</groupId>
<artifactId>
jsf-api</artifactId>
<version>
${mojarra.version}</version>
</dependency>
<dependency>
<groupId>
com.sun.faces</groupId>
<artifactId>
jsf-impl</artifactId>
<version>
${mojarra.version}</version>
<scope>
compile</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>
javax.servlet</groupId>
<artifactId>
jstl</artifactId>
<version>
${jstl.version}</version>
</dependency>
<!-- Servlet 2.5 -->
<dependency>
<groupId>
javax.servlet</groupId>
<artifactId>
servlet-api</artifactId>
<version>
${servlet-api.version}</version>
<scope>
provided</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>
junit</groupId>
<artifactId>
junit</artifactId>
<version>
${junit.version}</version>
<scope>
test</scope>
</dependency>
<!-- pretty faces -->
<dependency>
<groupId>
com.ocpsoft</groupId>
<artifactId>
prettyfaces-jsf2</artifactId>
<version>
${prettyfaces-jsf2.version}</version>
</dependency>
<!-- JAX WS RT -->
<dependency>
<groupId>
com.sun.xml.ws</groupId>
<artifactId>
jaxws-rt</artifactId>
<version>
${jaxws-rt.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- servlet -->
<dependency>
<groupId>
com.sun.faces</groupId>
<artifactId>
jsf-api</artifactId>
</dependency>
<dependency>
<groupId>
com.sun.faces</groupId>
<artifactId>
jsf-impl</artifactId>
<scope>
compile</scope>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>
javax.servlet</groupId>
<artifactId>
jstl</artifactId>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>
javax.servlet</groupId>
<artifactId>
servlet-api</artifactId>
<scope>
provided</scope>
</dependency>
<!-- pretty faces -->
<dependency>
<groupId>
com.ocpsoft</groupId>
<artifactId>
prettyfaces-jsf2</artifactId>
</dependency>
<!-- JAX WS RT -->
<dependency>
<groupId>
com.sun.xml.ws</groupId>
<artifactId>
jaxws-rt</artifactId>
</dependency>
</dependencies>
<build>
<finalName>
fibowebapp</finalName>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins</groupId>
<artifactId>
maven-eclipse-plugin</artifactId>
<version>
${maven-eclipse-plugin.version}</version>
<configuration>
<wtpversion>
${wtp.version}</wtpversion>
<source>
${java.version}</source>
<target>
${java.version}</target>
<downloadSources>
true</downloadSources>
<downloadJavadocs>
true</downloadJavadocs>
</configuration>
</plugin>
<!-- Tomcat plugin for embedded tomcat -->
<plugin>
<groupId>
org.codehaus.mojo</groupId>
<artifactId>
tomcat-maven-plugin</artifactId>
<version>
${tomcat-maven-plugin.version}</version>
<configuration>
<path>
/${project.build.finalName}</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
package
com.dvp.fibowebapp.ws;
import
javax.jws.WebParam;
import
javax.jws.WebService;
import
javax.jws.soap.SOAPBinding;
import
javax.jws.soap.SOAPBinding.Style;
import
com.dvp.fibowebapp.FiboResult;
import
com.dvp.fibowebapp.FiboService;
@WebService
@SOAPBinding
(
style =
Style.RPC)
public
class
FibonacciWebService {
private
final
FiboService fiboService =
FiboService.getInstance
(
);
public
Long fibonacci
(
@WebParam
(
name =
"rang"
) Integer rang) {
Long result =
fiboService.calculerFibonacci
(
rang);
return
result;
}
public
FiboDTO[] fibonacciList
(
@WebParam
(
name =
"rang"
) Integer rang, @WebParam
(
name =
"limit"
) Integer nb) {
int
size =
nb;
if
(
rang <
nb) {
size =
rang;
}
FiboDTO[] list =
new
FiboDTO[size];
for
(
int
i =
0
; i <
size; i++
) {
final
FiboResult fiboResult =
calculerFiboResult
(
rang -
i);
list[i] =
convert
(
fiboResult);
}
return
list;
}
private
FiboDTO convert
(
FiboResult fiboResult) {
FiboDTO fiboDTO =
new
FiboDTO
(
);
fiboDTO.setApproximation
(
fiboResult.getApproximation
(
));
fiboDTO.setRang
(
fiboResult.getRang
(
));
fiboDTO.setValeurApproximative
(
fiboResult.getValeurApproximative
(
));
fiboDTO.setValeurExacte
(
fiboResult.getValeurExacte
(
));
return
fiboDTO;
}
private
FiboResult calculerFiboResult
(
Integer rang) {
final
Long valeurExacte =
fiboService.calculerFibonacci
(
rang);
final
Long valeurApproximative =
fiboService.calculerApproximationfibonacci
(
rang);
final
FiboResult fiboResult =
new
FiboResult
(
rang, valeurExacte, valeurApproximative);
return
fiboResult;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<endpoints
xmlns
=
"http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version
=
"2.0"
>
<endpoint
name
=
"fibonacci"
implementation
=
"com.dvp.fibowebapp.ws.FibonacciWebService"
url-pattern
=
"/fibonacci"
/>
</endpoints>
<?xml version="1.0" encoding="UTF-8"?>
<web-app
version
=
"2.5"
xmlns
=
"http://java.sun.com/xml/ns/javaee"
xmlns
:
xsi
=
"http://www.w3.org/2001/XMLSchema-instance"
xsi
:
schemaLocation
=
"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
>
<!-- JSF 2 IMPLEMENTATION -->
<context-param>
<param-name>
javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>
.xhtml</param-value>
</context-param>
<!-- Enables special Facelets debug output during development -->
<context-param>
<param-name>
javax.faces.PROJECT_STAGE</param-name>
<param-value>
Development</param-value>
</context-param>
<!-- Causes Facelets to refresh templates during development -->
<context-param>
<param-name>
javax.faces.FACELETS_REFRESH_PERIOD</param-name>
<param-value>
1</param-value>
</context-param>
<context-param>
<param-name>
javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>
true</param-value>
</context-param>
<!-- Web service -->
<listener>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
<servlet-name>
WSServlet</servlet-name>
<servlet-class>
com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
<load-on-startup>
1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>
WSServlet</servlet-name>
<url-pattern>
/fibonacci</url-pattern>
</servlet-mapping>
<!-- Pretty faces -->
<filter>
<filter-name>
Pretty Filter</filter-name>
<filter-class>
com.ocpsoft.pretty.PrettyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>
Pretty Filter</filter-name>
<url-pattern>
/*</url-pattern>
<dispatcher>
FORWARD</dispatcher>
<dispatcher>
REQUEST</dispatcher>
<dispatcher>
ERROR</dispatcher>
</filter-mapping>
<!-- Faces -->
<servlet>
<servlet-name>
facesServlet</servlet-name>
<servlet-class>
javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>
1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>
facesServlet</servlet-name>
<url-pattern>
*.jsf</url-pattern>
</servlet-mapping>
<!-- Default page -->
<welcome-file-list>
<welcome-file>
index.html</welcome-file>
</welcome-file-list>
</web-app>