SMS-U version 2
AngularJS, Web widget, REST/JSON
Pascal.Rigaux @ univ-paris1.fr
Plan
- Présentation
- Single Page Application
- AngularJS
- Web widget
- Authentification
- Problèmes rencontrés
Présentation
- service d'envoi de SMS
- développé dans le cadre de l'UNPIdF avec un financement de la Mairie de Paris
- développement initial réalisé par un prestataire
Fonctionnalités
- envoi à des groupes
- gestion de quotas
- gestion des modérateurs
- gestion des accusés de réception (l'envoi de SMS est asynchrone)
Présentation
SMS-U à Paris 1
- Notre LDAP connait le numéro de portable de :
- 80% des étudiants
- 33% du personnel
- Personnes ayant autorisé SMS-U (opt-in)
- 50% des étudiants
- 20% du personnel
Présentation
Utilisations à Paris1 en 2013/2014
En un an, 18000 SMS envoyés ➡ 1000 € (0.05€/sms)
- Principaux consommateurs :
- 8500 SMS : pédagogique et administratif
(dont 50% service des sports, 30% UFR 12)
- 8000 SMS : ré-initialisation de mot de passe
- Nouveautés cette année :
- rendez-vous médicaux et administratifs
- alertes climatisation
Présentation
Migration technologique
ant |
➡ |
maven + ant |
JSF |
➡ |
AngularJS |
SOAP |
➡ |
REST/JSON |
desktop |
➡ |
responsive web design |
servlet / portlet |
➡ |
servlet / web widget |
groupes PAGS |
➡ |
groupes LDAP / wsgroups |
Single Page Application
Tout est fait en Ajax !
L'application mono-page la plus connue : Gmail
Petite démonstration avec SMS-U v2...
Pour accéder à SMS-U, authentification classique
On clique sur « Envoi SMS »...
Remarquez l'URL
On clique sur « Envoyer »...
Remarquez l'URL
(permet le lien en profondeur)
Un autre envoi
Au moment d'envoyer, la session est expirée...
On clique sur « Envoyer »...
On clique pour se logger à nouveau
Un nouvel onglet est ouvert !
window.open + postMessage
... le message a été envoyé !
L'expiration n'a pas été un problème :)
Pendant le redémarrage du serveur ?
L'utilisateur est prévenu...
Quand le serveur est démarré
l'application reprend là où elle en était
Comme l'application démarre assez vite, ce redémarrage passera souvent inaperçu
re-log transparent sur CAS avec JSONP
Single Page Application
- toute la navigation est faite en Ajax
- toutes les actions sont faites en Ajax :
➡ on s'abstrait des contraintes des <form> HTML
➡ les données client->serveur peuvent être complexes
- templates manipulés dans le navigateur ➡ cache
- routage avec URLs ...#/send
(NB : HTML5 permet de faire plus transparent avec pushState)
- les données de navigation sont conservées en mémoire dans le navigateur
- la session java ne stocke que le login ! re-log transparent
- debug facile dans le navigateur
⚠ programmation asynchrone !
AngularJS
fantastique framework javascript
- MVC
- liaison bidirectionnelle des données comme dans JSF
➡ pas de manipulation du DOM, sauf dans les directives
- injection de dépendances comme dans Spring
- documentation, exemples éditables (jsfiddle, plunk)
- sécurité (avec porte de sortie : Strict Contextual Escaping), routage, validateurs de formulaires, framework de tests
- intégration en cours dans les navigateurs (web components : object.observe, templates)
Démonstrateur de l'interface utilisateur (purement dans le navigateur avec mock web-service)
Je vous invite à aller tester !
Tests d'interface pour vérifier automatiquement la compatibilité dans différents navigateurs
NB: Protractor replaces deprecated AngularJS Scenario Runner
AngularJS vs JSF
inconvénients d'AngularJS
- le code serveur doit être plus fiable, le spoofing des paramètres d'entrée étant facile
- validateurs souvent dupliqués côté client
- rôles vérifiés côté client et côté serveur
avantages d'AngularJS
- réactivité de l'interface
- facile, léger
- bonne intégration avec le javascript :)
- simple de faire des composants UI réutilisables (les "directives")
Web widget
Définition
Widget intégrable dans une page web :
- ne maîtrise pas l'url de la page
- peut utiliser un web service
Web widget
Utilisation dans uPortal
Il faut autoriser le portail à utiliser le web service SMS-U :
# dans config.properties:
portal.urls=http://up4-unpidf.univ-paris1.fr
Multiples possibilités d'intégration :
CMS, WebProxy, JSR 168.
Pour uPortal 4, créer un canal « Advanced CMS » et mettre :
<script src="https://sms.univ-paris1.fr/WebWidget.js">
Voilà le résultat.
Ça ressemble à une portlet java !
Mais en fait, cela fait des requêtes cross-domain directement vers le web service https://sms.univ-paris1.fr/rest
Web widget vs Portlet
Web widget | Portlet |
toute techno serveur | seulement JVM |
même serveur ou ailleurs | même tomcat/java |
gère authentification & session | délègue authentification & session |
gère son autorisation | peut déléguer l'autorisation |
urls #/send
➡ attention aux conflits si plusieurs SPA dans la page | urls remapped pour passer par uPortal (qui fait l'agrégation html)
(si plusieurs portlets dans la page, l'url contient les paramètres pour une portlet, les autres portlets utilisent les paramètres enregistrés en session)
|
Web widget vs Portlet
avantages du web widget
- pas lié à un seul portail
➡ intégrable dans plusieurs portails
- pas lié à un seul tomcat
➡ décentralisation de la maintenance, gestion, charge
- navigation Ajax
➡ plus réactif, plus rapide sur mobile
inconvénients du web widget
- authentification délicate
Authentification
Pour authentifier un web service depuis le navigateur :
possibilité | contraintes |
classique |
maitriser l'url de la page |
window.open + postMessage |
clic utilisateur |
JSONP | auth préalable, third party cookies, pas shibboleth |
iframe cachée | auth préalable, third party cookies |
Authentification
Shibboleth
La fédération Éducation-Recherche utilise le binding « HTTP Post ».
Cela rend difficile l'authentification :
- JSONP : impossible
- iframe cachée : possible mais impossible de savoir si l'authentification a échoué ou est en cours
Solution :
- tester un login automatique dans une iframe cachée
- tout en proposant un login explicite avec window.open
NB :
l'utilisation du binding « HTTP Artifact » rendrait le mécanisme similaire à CAS.
Cela éviterait aussi les syndromes « page blanche » et « action "page précédente" impossible »
Authentification
Web widget sur site externe
Safari refuse les cookies des sites non visités. Cela concerne uniquement les sites externes.
Un web widget peut contourner le problème en gardant l'id de session dans sessionStorage ou en mémoire.
- Java CAS Client : facile ➡ fait dans SMS-U (redirectAfterValidation + jsessionid dans l'URL)
- phpCAS : facile
(setNoClearTicketsFromUrl + sessionId en HTTP header)
- Shibboleth SP : impossible, cookies obligatoires
- SimpleSAMLphp, OpenSAML... : à tester
Problèmes rencontrés
Dette technique dans le code java existant
- requêtes SQL construite à la main, sans escaping !
- champs base de données limités à des strings très petites
- différences entre create_tables.sql et *.hbm.xml
- param hibernate MysqlInnodb plutôt Mysql5Innodb
- duplication de code entre les sous-projets
(DAO POJOs, *.hbm.xml, WS exceptions, WS beans)
- librairies obsolètes (commons-httpclient, xfire)
Problèmes rencontrés
Java
- maven
- peu de gestion de conflits entre jars
- xercesimpl vs xml-apis
- conflicting versions (jackson-*, spring-*...)
- opensaml obsolete deps
- lent en ligne de commande
- complexe comparé à ant
- manque d'outils pour la gestion des css/js
- tentative de rester à hibernate, en remplaçant la gestion des sessions hibernate esup-commons par OpenSessionInView
➡ échec ➡ autocommit=true
Problèmes rencontrés
outils pour la gestion des css/js
| Java | node.js |
concaténation | yuicompressor | grunt-concat |
minification | yuicompressor | grunt-usemin |
vérification de code | jshint-maven-plugin (lent) | grunt-contrib-jshint |
cache buster | jasig resource-server (wro4j namingStrategy?) | grunt-rev |
download libs | webjars | bower |
custom jquery | ? | grunt-jquery-builder |
angular templates | ? | grunt-angular-templates |
NB : les webjars ne fournissent pas de liste ordonnée pour concaténation, par contre possibilité d'utiliser require.js
Problèmes rencontrés
Java
- jackson est bien, mais plus compliqué qu'en PHP ou node.js
- spring-ldap : faire une requête spécifique à l'attribut "members" pas possible
(solution utilisée : bean spécifique pour accéder à "members")
- eclipse trouve pas les sources pour le debug
(solution utilisée : remote debugging)
- JAX-RS : si utilisé pour proposer du JSON ou du XML,
nécessite Accept-Content-Type rendant l'url difficile à tester dans le navigateur
- jetty servlet3 : lenteur démarrage si classpath scanning (pb disparu !?)
- UI beans avec setters/getters ralentissent la ré-architecturation
- interfaces entre controller et business ralentissent la ré-architecturation
Problèmes rencontrés
AngularJS
- conflit avec le routage jquery-mobile dans uPortal 4 (solution)
- les « directives » sont difficiles à manipuler en dehors des cas documentés
- prévenir les clics doublés pendant l'attente
- danger du ng-model si pas de "."
Conclusion
- la version 2 de SMS-U est plus réactive
- 90% code java DAO/business inchangé
- AngularJS très bien
Questions ?