XII. Objectifs du Front-end▲
L'application Library développée et présentée dans la page précédente, dispose d'une API REST composée de web services concourant à répondre aux besoins exprimés dans les Users Stories. Dans ce contexte, elle ne peut gagner toute son utilité que s'il existe une ou plusieurs application(s) cliente(s) qui consomme(nt) les web services exposés.
Dans cette partie de notre article, notre objectif est de développer un client web, baptisé Library-ui, qui offrira une vue IHM (Interface Homme Machine) pour la gestion de la bibliothèque. Ce client web sera composé de pages web pour l'administration des livres, des clients et des prêts. Il disposera aussi d'un menu général permettant de naviguer vers les différentes pages. Chacune de ces pages comportera un bouton back permettant de retourner sur le menu général. Library-ui devra être un site web dynamique qui consomme de les APIs REST exposées en Back-end dans le projet Library, afin de permettre à l'administrateur de l'application de réaliser tous ses besoins.
Pour ce faire, nous avons selectionné le framework Angular qui nous permettra d'atteindre cette spécification. Sa version au moment où nous developpions cette application était la 7.
Au terme de cette partie, nous allons construire une application purement cliente dont la figure ci-dessous illustre les différents composants :
Les différents composants coloriés en jaune sont les suivants :
- Le composant Book, qui proposera une page web pour la création, mise-à-jour, lecture et suppression de livres
- Le composant Customer, qui proposera une page web pour la création, mise-à-jour, lecture et suppression de clients
- Le composant Loan, qui proposera une page web pour la création, mise-à-jour, lecture et suppression de prêts
- Le composant menu, pour la gestion du menu général
- Le composant modal, incorporé dans le composant Loan, qui proposera une fenêtre modale permettant d'envoyer des mails
XIII. Mise en place du projet Angular Library-ui▲
XIII-A. Préambule et notions de base▲
Angular est un framework basé sur le langage TypeScript (une surcouche du Javascript). Sa philosophie, comme celle de nombreux frameworks concurrents (Vue.js, React.js, etc), peut se résumer par la phrase suivante : proposer un nouveau paradigme de construction de sites web qui améliore l'expérience utilisateur. Plus simplement, cela veut dire, l'optimisation du temps de réponse et donc de la performance des pages web visitées par une tierce personne lorsqu'elle navigue sur un site web. Pour atteindre cet objectif, Angular s'appuie sur deux politiques architecturales majeurs :
- La notion de Single Page Application (SPA) : Il s'agit d'une approche qui consiste à considérer les différentes pages web d'un site comme des composants devant tous être incorporés dans une seule et unique page principale. Seule cette page principale est reconnue et gérée par le navigateur. Par des mecanismes très poussés que propose le framework, il sera alors possible de jouer sur l'affichage ou pas de différents composants dans cette page principale afin de donner l'impression à l'utilisateur qu'il navigue sur des pages web différentes.
- La maximisation des traitements côté client : cette approche permet de créer des sites web dynamiques où la grande majorité des traitements derrière tout composant est exécutés côté client, c'est-à-dire votre navigateur web (Chrome, Mozilla, IE, etc). Seuls les traitements nécessitant la consommation d'une API REST feront appel au serveur en Back-end.
La philosophie ci-dessus expliquée du framework Angular se distingue donc de celle des technologies comme JSP/JSTL, PHP, etc, où le serveur heberge plusieurs pages web et se charge de les servir à votre navigateur à chaque requête. Cette approche provoque ainsi une actuallisation par rechargement des pages sur le navigateur à la moindre action utilisateur. Ce qui provoque une perte de temps et une navigation dégradée. Or avec la politique SPA, les requêtes du client vers le serveur n'implique pas un rechargement de la page principale hébergée sur le serveur. Celle-ci n'est en effet chargée qu'une seule fois lors du démarrage de l'application cliente.
Angular fait partir des frameworks basés sur la plateforme node.js. Node.js est un outil offrant, entre autres, la possibilité de compiler et d'exécuter du code Angular en phase de développement sur un poste de travail. Il s'installe aisément sur votre poste de travail. Angular s'appuie aussi sur le repository npm (désormais intégré dans node.js)pour vous permettre de d'installer des modules qui lui permettent de vous offrir de nombreuses fonctionnalités exploitables dans votre projet Angular.
Pour l'installation de node.js/npm, nous vous demandons de suivre le lien suivant https://nodejs.org/fr/ pour télécharger l'installateur et l'installer sur votre machine en suivant les indications.
Enfin, pour développer une application Angular, il faut un IDE (Integrated Developpement Environnement) approprié. Sur Eclipse, il existe le plugin Angular Eclipse d'Angelo Zerr, à installer via la MarketPlace. On peut aussi utiliser l'IDE gratuit Visual Studio Code qui intègre déjà tout le nécessaire pour développer des projets Angular. Enfin, il existe aussi l'IDE payant Angular IDE. Nous faisons le choix pour cet article d'utiliser Visual Studio Code.
Pour terminer cette section, si vous avez besoin de plus d'informations sur la notion de Single Page Application, vous pouvez lire les contenus suivants : Arolla, Octo.
XIII-B. Création du projet Library-ui▲
Maintenant que vous avez installé node.js/npm et Visual Studio Code pour la plateforme de développement, nous sommes presque prêts pour la création du projet Angular Library-ui. Mais avant cette opération, il est nécessaire d'installer Angular CLI. Angular CLI est un outil permettant de créer et de gérer aisément le cycle de vie d'un projet de type Angular. Toute proportion gardée, on peut voir Angular CLI comme le maven des projets Java. Au moment de développer ce projet, Angular CLI était à la version 7.3.3 correspondant donc à la version 7 du framework Angular. Son installtion se réduit à l'instruction suivante dans un terminal et dans n'importe quel repertoire de poste de travail :
npm install -g
@angular/
cli@7
.3
.3
Maintenant nous pouvons donc créer notre projet à l'aide de la commande :
ng new Library-
ui
Le projet imagé sur la figure ci-dessous est donc créé et il ne reste plus qu'à l'ouvrir avec notre IDE pour le compléter. Le répertoire /src représente celui dans lequel nous ajouterons nos code sources.
XIII-C. Configuration du projet▲
Lors de la phase de développement, le framework Angular utilise le port 4200 sur votre localhost pour visualiser en temps réel les IHM développées. L'url d'accès est donc la suivante : http://localhost:4200.
Nous voulons par ailleurs que notre application soit accessible via le lien http://localhost:4200/library-ui où library-ui est le point d'entrée de l'application permettant d'afficher le menu. configurer. Enfin, et comme nous l'avons expliqué, notre application Library-ui communiquera avec le Back-end à l'aide d'appel REST. Il est donc important que nous vous presentions comment cela est mis en place.
1. Modification du fichier Package.json
Dans le repertoire d'installation du projet Library-ui (voir capture ci-dessus), ouvrez le fichier Package.json et modifiez la ligne coloriée en jaune pour ajouter l'instruction suivante : --base-href /library-ui --proxy-config proxy.conf.json.
- la commande --base-href /library-ui, permet de marquer l'accessibilité de la page web principale sur le siffixe /library-ui. Exemple : la saisie de l'url http://localhost:4200/library-ui permettra d'afficher le menu principal
- la commande --proxy-config proxy-conf.json, permet d'indiquer l'adresse des différents différents serveurs côté Back-end auxquels l'application cliente Angular peut être amenée à appeller. En d'autres termes, c'est dans ce fichier que l'on configure les urls des serveurs qui hebergent les APIs REST auxquels Library-ui va faire appel.
2. Création du fichier proxy-conf.json
Dans le repertoire d'installation du projet Library-ui (voir capture ci-dessus) et au même niveau que le fichier package.json, créez le fichier de nom proxy-conf.json et ajouter le contenu présentez sur la capture. Pour aller plus loin sur la configuration vous pouvez consulter le lien suivant. Notez que le contenu de ce fichier indique que le serveur Back-end répond sur l'url http://localhost:8082 en n'admettant uniquement les requêtes http contenant le prefixe /library. Cette configuration s'adapte donc aux URI de nos APIs REST exposés dans le projet Library côté Back-end dans les contrôleurs REST.
Une fois les deux premières configurations ci-dessus effectuées, ouvrez le fichier angular.json et dans la rubrique serve, ajouter la commande "proxyConfig": "src/proxy.conf.json". il suffit de se position à la racine du repertoire du projet Library-ui et d'exécuter la commande npm start sur un terminal pour démarrer l'exécution de cette application.
3. Dossier ressources
Notez, que le projet Library-ui contient un dossier nommé assets obtenu lors de la création du projet à l'aide de la commande ng new... Ce dossier assets est destiné à contenir tous les fichiers ressources de l'application à l'instar des images. C'est ce que nous avons fait en ajoutant l'image que vous visualiserez sur la page de menu de l'application.
4. Configuration du spinner
Nous avons rajouté un spinner dans notre application Library-ui. Cela nécessite d'installer un nouveau module nommé ngx-spinner. Pour rappel, un Spinner est un composant HTML graphique et dynamique qui permet de signaler l'indisponibilité totale d'une page web quand il est entrain de charger les éléments constituants son contenu. Pour en savoir plus sur son installation et sa configuration, suivre le lien suivant.
5. Configuration du DatePicker
Sur nos pages HTML, nous aurons besoin d'utiliser des calendriers afin de completer des champs de saisie avec des dates (ex : date de sortie d'un livre, date de début d'un prêt, etc); Pour ce faire, Angular propose un module offrant des outils permettant de gérer aisément l'affichage et la manipulation d'un calendrier dans un élément HTML de type input. Cependant, ce module n'est pas présent dans la liste des modules de base obtenus lors de l'installation de l'Angular CLI. Nous devons donc installer le module Angular Material. Vous pouvez suivre le lien suivant, pour comprendre comment nous l'avons intégré dans notre application.
XIV. Pages web et Services HttpClient▲
Dans cette partie, nous présentons succintement les trois différentes pages web que nous avons développées pour gérer respectivement les livres, clients et prêts. Nous présentons aussi les services Angular associés permettant de consommer les APIs REST exposées côté Back-end. Comme nous vous l'avons expliqué dans la section précédente, le terme page web est un abus de langage d'un point de vue Angular. En effet, ce framework crée et gère des composants HTML qu'il intègre dans une seule et unique page principale (l'index.html située à la racine du projet). Ainsi donc, dans le sens pur du terme, Angular permet de développer des composants.
Pour créer un composant Angular, allez dans le répertoire library-ui/src/app et saisir la commande suivante :
ng g component <nom-
composant>
Cette commande nous permettra de créer respectivement les composants Book-page, Customer-page, Loan-page, etc. Leurs dossiers respectifs seront générés et contiendrons les fichiers d'extension : .html, .css, .ts et .spec.ts. Exemple :
- le fichier d'extension .html, est un fichier template qui contient tous les éléments HTML nécessaires à l'affichage du composant
- le fichier d'extension .css, contient les instructions de style pour le .html
- le fichier d'extension .ts, contient une classe dans laquelle nous allons devélopper nos fonctions TypeScript afin de répondre au besoin métier que doit gérer le composant. Ce fichier .ts contient donc toutes les variables utilisées par le .html pour afficher dynamiquement des données. Par ailleurs, le .html transmettra des informations au .ts à travers l'émission d'évenments basés sur des fonctions devéloppées dans ce dernier. Enfin, notez que ce sont les fonctions développées dans le .ts qui consommeront réellement les APIs REST exposées côté Back-end.
- le fichier d'extension .spec.ts, correspond au fichier de tests unitaires des fonctions développées dans le .ts
Pour des raisons de clarté Architecturale, nous avons créé, pour chaque composant Book-page, Customer-page et Loan-page, une classe de services regroupant les différents appels REST nécessaires à la page. Ainsi donc, le fichier .ts de chaque composant n'aura plus qu'à appeler cette classe pour consommer les différents web service. Pour implémenter nos classes de services, nous avons créer un dossier services dans le répertoire library-ui/src/app et y avons exécuté la commande suivante
ng g service <nom-
service>
Pour la suite de cette partie, nous vous exposons le rendu de chacune des composants ainsi que la classe de services associée. Nous laissons le soins au lecteur de s'en approprier du code source développé dans chacune des composants. Les source de l'application sont disponibles à la fin de cet article.
XIV-A. Composant Book et ses Services d'appel REST▲
Dans cette section, nous vous présentons la page de gestion des livres que nous avons développée. Vous pourrez retrouver son code source dans le composant src/app/book du projet Library-ui :
Cette page a pour besoin de consommer les différents web services exposés côté Back-end dans le contrôleur BookRestController. La classe de service baptisée BookService définie dans le fichier /src/app/services/book.service.ts, injecte via son cosntructeur, l'objet HttpClient fourni par Angular afin de pouvoir consommer des web services :
import
{
Injectable }
from
'@angular/core'
;
import
{
Observable }
from
"rxjs"
;
import
{
Category }
from
"src/app/models/category"
;
import
{
HttpClient,
HttpHeaders }
from
"@angular/common/http"
;
import
{
Book }
from
"src/app/models/book"
;
@Injectable
({
providedIn
:
'root'
}
)
export
class
BookService {
constructor
(
private
http
:
HttpClient) {
}
/**
* Get all book's categories as reference data from Backend server.
*/
loadCategories
(
):
Observable<
Category[]>{
let
headers =
new
HttpHeaders
(
);
headers.
append
(
'content-type'
,
'application/json'
);
headers.
append
(
'accept'
,
'application/json'
);
return
this
.
http.
get
<
Category[]>(
'/library/rest/category/api/allCategories'
,
{
headers
:
headers}
);
}
/**
* Save a new Book object in the Backend server data base.
* @param book
*/
saveBook
(
book
:
Book):
Observable<
Book>{
return
this
.
http.
post<
Book>(
'/library/rest/book/api/addBook'
,
book);
}
/**
* Update an existing Book object in the Backend server data base.
* @param book
*/
updateBook
(
book
:
Book):
Observable<
Book>{
return
this
.
http.
put<
Book>(
'/library/rest/book/api/updateBook'
,
book);
}
/**
* Delete an existing Book object in the Backend server data base.
* @param book
*/
deleteBook
(
book
:
Book):
Observable<
string
>{
return
this
.
http.
delete
<
string
>(
'/library/rest/book/api/deleteBook/'
+
book.
id);
}
/**
* Search books by isbn
* @param isbn
*/
searchBookByIsbn
(
isbn
:
string
):
Observable<
Book>{
return
this
.
http.
get
<
Book>(
'/library/rest/book/api/searchByIsbn?isbn='
+
isbn);
}
/**
* Search books by title
* @param title
*/
searchBookByTitle
(
title
:
string
):
Observable<
Book[]>{
return
this
.
http.
get
<
Book[]>(
'/library/rest/book/api/searchByTitle?title='
+
title);
}
}
HttPClient fourni entre autre, plusieurs méthodes permettant de faire des appels REST : get(), delete(), put(), post(). Chacune de ces méthodes prend en entrée l'URI du web service concerné et retourne un objet Observable encapsulant l'objet de retour du web service. La classe Observable fournissant de son côté des méthodes permettant d'exploiter l'objet de retour. C'est ce qui est fait dans le fichier book-page.component.ts.
XIV-B. Composant Customer et ses Services d'appel REST▲
Dans cette section, nous vous présentons la page de gestion des clients que nous avons développée. De même, vous pourrez retrouver son code source dans le composant src/app/customer du projet Library-ui :
Cette page a pour besoin de consommer les différents web services exposés côté Back-end dans le contrôleur CustomerRestController. De même la classe de services baptisée CustomerService et définie dans le fichier /src/app/services/customer.service.ts, expose les différents appels :
import
{
Injectable }
from
'@angular/core'
;
import
{
HttpClient,
HttpHeaders }
from
'@angular/common/http'
;
import
{
Observable }
from
'rxjs'
;
import
{
Customer }
from
'../models/customer'
;
@Injectable
({
providedIn
:
'root'
}
)
export
class
CustomerService {
constructor
(
private
http
:
HttpClient) {
}
/**
* Save a new Customer object in the Backend server data base.
* @param book
*/
saveCustomer
(
customer
:
Customer):
Observable<
Customer>{
return
this
.
http.
post<
Customer>(
'/library/rest/customer/api/addCustomer'
,
customer);
}
/**
* Update an existing Customer object in the Backend server data base.
* @param customer
*/
updateCustomer
(
customer
:
Customer):
Observable<
Customer>{
return
this
.
http.
put<
Customer>(
'/library/rest/customer/api/updateCustomer'
,
customer);
}
/**
* Delete an existing Customer object in the Backend server data base.
* @param customer
*/
deleteCustomer
(
customer
:
Customer):
Observable<
string
>{
return
this
.
http.
delete
<
string
>(
'/library/rest/customer/api/deleteCustomer/'
+
customer.
id);
}
/**
* Search customer by email
* @param email
*/
searchCustomerByEmail
(
email
:
string
):
Observable<
Customer>{
return
this
.
http.
get
<
Customer>(
'/library/rest/customer/api/searchByEmail?email='
+
email);
}
/**
* Search books by pagination
* @param beginPage
* @param endPage,
*/
searchCustomerByLastName
(
lastName
:
string
):
Observable<
Customer[]>{
return
this
.
http.
get
<
Customer[]>(
'/library/rest/customer/api/searchByLastName?lastName='
+
lastName);
}
}
XIV-C. Composant Loan et ses Services d'appel REST▲
Dans cette section, nous vous présentons la page de gestion des prêts que nous avons développée. Le code source qui permit la construction de ce composant est situé dans le dossier src/app/loan du projet Library-ui :
Cette page a pour besoin de consommer les différents web services exposés côté Back-end dans le contrôleur LoanRestController. Sa classe de services baptisée LoanService et définie dans le fichier /src/app/services/loan.service.ts est la suivante :
import
{
Injectable }
from
'@angular/core'
;
import
{
SimpleLoan }
from
'../models/simple-loan'
;
import
{
Loan }
from
'../models/loan'
;
import
{
Observable }
from
'rxjs'
;
import
{
HttpClient,
HttpHeaders }
from
'@angular/common/http'
;
import
{
Mail }
from
'../models/mail'
;
@Injectable
({
providedIn
:
'root'
}
)
export
class
LoanService {
constructor
(
private
http
:
HttpClient) {
}
/**
* Save a new simpleLoan object in the Backend server data base.
* @param book
*/
saveLoan
(
simpleLoan
:
SimpleLoan):
Observable<
Loan>{
return
this
.
http.
post<
Loan>(
'/library/rest/loan/api/addLoan'
,
simpleLoan);
}
/**
* Close an existing loan object in the Backend server data base.
* @param loan
*/
closeLoan
(
simpleLoan
:
SimpleLoan):
Observable<
Boolean
>{
return
this
.
http.
post<
Boolean
>(
'/library/rest/loan/api/closeLoan/'
,
simpleLoan);
}
/**
* Search Loans by email
* @param email
*/
searchLoansByEmail
(
email
:
string
):
Observable<
Loan[]>{
return
this
.
http.
get
<
Loan[]>(
'/library/rest/loan/api/customerLoans?email='
+
email);
}
/**
* Search Loans by maximum date
* @param maxDate
*/
searchLoansByMaximumDate
(
maxDate
:
Date
):
Observable<
Loan[]>{
let
month
:
string
=
maxDate.
getMonth
(
) <
10
?
'0'
+(
maxDate.
getMonth
(
)+
1
):
''
+(
maxDate.
getMonth
(
)+
1
);
let
dayOfMonth
:
string
=
maxDate.
getDate
(
) <
10
?
'0'
+
maxDate.
getDate
(
):
''
+
maxDate.
getDate
(
);
let
maxDateStr
:
string
=
maxDate.
getFullYear
(
) +
'-'
+
month +
'-'
+
dayOfMonth;
return
this
.
http.
get
<
Loan[]>(
'/library/rest/loan/api/maxEndDate?date='
+
maxDateStr);
}
/**
* Send an email to a customer
* @param mail
*/
sendEmail
(
mail
:
Mail):
Observable<
boolean
>{
//let headers = new HttpHeaders();
//headers.append('responseType', 'arraybuffer'); , {headers: headers}
return
this
.
http.
put<
boolean
>(
'/library/rest/customer/api/sendEmailToCustomer'
,
mail);
}
}
XIV-D. Le menu principal▲
Nous avons développé une page principale servant de menu et permettant de naviguer d'une page à l'autre. Son code source se trouve dans le dossier /src/app/menu/menu. Par contre ce composant ne fait pas d'appel REST. Il n'y a donc pas de classe de service pour cette dernière.
Dans la page suivante, nous allons vous présenter comment faire un déploiement de notre application (Front-end et Back-end) sur un serveur tomcat. Nous vous présenterons aussi une vidéo qui dans laquelle nous présentons l'application en live.