Affichage des articles dont le libellé est javascript. Afficher tous les articles
Affichage des articles dont le libellé est javascript. Afficher tous les articles

dimanche 31 mars 2013

Retour sur DevoxxFr 2013


















Les cast codeurs viennent de nous dire au revoir, c'est le signal de clôture de cette édition 2013 de Devoxx France… Je vais vous tenter de vous livrer mes impressions encore tièdes et vous propose de partager les faits qui m'ont marqué au cours de ces trois jours intenses!






On n'attire pas les mouches avec du vinaigre. Nous, les geeks de 2013, avons la chance d'évoluer à une époque au cours de laquelle il semble que la demande soit inférieure aux offres d'emploi tandis que les autres corporations traversent la crise. Rappelons que cela n'a pas toujours été le cas, car il y a maintenant une douzaine d'années, lorsque les caps du passage à l'euro et Y2K ont été passés, la bulle internet a éclaté et le marché est devenu assez terne durant quelques années. Séquence "nostalgie qui ne me rajeunit pas" et "j'apprécie ce que j'ai". Donc un nombre important de stands étaient tenus par des entreprises qui exposaient autant pour proposer leurs services que pour faire leurs emplettes sur le marché des consultants. Et comment attirer l'attention des membres d'une population majoritairement masculine? Avec de charmantes managers, commerciales ou encore chargée de recrutement. Oui Mr GONCALVES, chevalier blanc tout de


rose
noir vêtu, après le
procès d'intention dressé contre Sony au sujet d'une affiche misogyne d'un gout douteux, j'attends un nouveau plaidoyer pour dénoncer l'instrumentalisation de la femme à Devoxx!

















Goodies. Ne stigmatisons pas il n'y avait pas que ça pour attirer le geek sur les stands. Et tradition oblige, pour récolter des contacts les exposants nous ont distribué des t-shirts, des mugs, des clefs USB, des autocollants, des lingettes, des boîtes à meuh, de la bière à la pression, des friandises et des décapsuleurs! D'ailleurs je décerne la palme du Goody à RedHat pour son décapsuleur OpenShift qui est bien supérieur à celui d'Oracle puisque celui-ci a en plus une capacité de 4Go. J'aurais payé pour l'avoir et il ne m'a coûté que mon adresse mail. Bref une belle ambiance.













Un parfum d'USI? La première keynote de cette année a été une surprise avec une rétrospective sur l'histoire des écritures. Clarisse Herrenschmidt a balayé devant nous 6000 ans d'évolutions des signes pour nous amener habilement à réfléchir sur la transition dont nous sommes les acteurs. Ca m'a fait penser à la  conférence de Michel SERRES à l'USI. En tout cas une très bonne idée. 


Ensuite, Stephan JANSEN nous a présenté la finalisation de la transition Flash vers HTML5 sur Parleys. Ca déchire le prépuce… S'il subsistaient dans la salle des HTML5 sceptiques, il y a fort à parier qu'il y en a un peu moins aujourd'hui.


Devoxx a également accueilli Martin ODERSKY, invité de marque puisqu'il n'est autre que le "papa" de Scala. Là les choses ont été différentes… J'en ai déjà parlé, Scala a tendance à diviser et ce talk ne me paraît pas avoir arrangé les choses. Rapidement des slides sont apparues mettant dos à dos du code Scala et Java pour mettre en valeur la concision du premier face à la verbosité de second. Quand il finit par avancer que les adeptes de la programmation fonctionnelle et ceux de l'orienté objet pourraient être réunis s'ils développaient en Scala, je me suis levé et je suis parti. Mr ODERSKY, j'aime le vent de fraîcheur qu'apporte votre langage dans le paysage mais j'ai détesté votre keynote. 






Mon DevoxxFr 2013 s'est composé essentiellement de conférences et elles furent pour la plupart riches et les thèmes présentés confirment les tendances hype: technos front avec HTML5 et JS (un zeste de Dart et TypeScript), DevOps, Cloud, programmation fonctionnelle, Big Data et évidemment tout ce qui touche au langage Java et à JavaEE puisqu'ils font évidemment partie des fondamentaux. A noter qu'un virus s'est répandu dans les différents sujets, le Raspberry Pi: Java Fx sur Pi, WAS sur Pi, piloter un Pi avec un minitel et j'en passe… j'ai eu l'impression de voir le remix de la collection des "Martine" dans lequel l'héroïne aurait cédé sa place à l'ordinateur à 20$.  


 Et au passage, j'aimerais témoigner de la qualité de la sélection des talks "indépendants" car tous ces sujets ne m'ont pas forcément intéressé mais ils présentaient en moyenne une qualité élevée et il y en avait pour tous les niveaux. Je précise "indépendants" (ne veux pas dire menés par des free-lances) car il y avait également les "partner slots": des confs qui sont réservés pour les entreprises qui sponsorisent l'évènement. Et là il y a eu des #fails à mon goût. DevoxxFr est une conf de techos: ils veulent voir du code et même du live coding, du protocole, de l'exécution, mais pas une plaquette produit exportée au format PowerPoint. Pire certains l'ont visiblement fait en connaissance de cause pariant sauver les meubles avec un titre racoleur genre "les secrets d'optimisation de performance d'un superhero", et paf des features tout le long. Sanction: je me lève et je pars. Messieurs les sponsors, je ne milite évidemment pas pour une éviction des partner slots, vos solutions sont loin d'être dénuées d'intérêt mais j'attends de la démo, du log ou de la capture de trame, bref je veux que vous me mettiez le nez sous le capot  avant de montrer la valeur de votre produit. DevoxxFr est, pour nous les informaticiens, l'occasion de collecter du savoir, nous ne pouvons pas nous contenter d'un spot pub de 50 minutes. J'ai échangé avec d'autres participants et mon n'avis n'est pas isolé, j'ai même entendu "quand je vois que c'est un partner slot, je n'y vais même pas". Il paraît nécessaire que la copie soit revue et que vous partagiez avec nous. Si un boycott se généralisait, tout le monde serait perdant. Notons que je n'ai pas participé à tous les talks sponsorisés et que j'en ai vu certains qui répondaient à mes exigences, tous ne s'inscrivent donc pas dans cette démarche.






"Compile once, run everywhere" Depuis 1995 on nous raconte une belle histoire en vantant les mérites de cette technologie qui pose une couche d'abstraction entre le matériel et le code source. Aujourd'hui l'abstraction proposée par la programmation fonctionnelle nous éloigne encore un peu plus du hardware. Parmi tous les speakers, j'ai trouvé un extra terrestre: Martin THOMPSON. Pourquoi un extra terrestre? Eh bien ses propos sont anachroniques mais remettent clairement en question ce détachement: comment éviter des invalidation de cache de CPU (avec du padding), les gains apportés par un modèle mémoire prévoyant d'exploiter des segments contigus, les lenteurs identifiées tardivement à cause de différences entre la plateforme de développement et l'environnement d'exploitation et j'en passe. Tout est donc bousculé. Si le tuning que nous devons apporter à notre code tient compte de ces considérations, il devient par là même spécifique à une architecture matérielle et me voilà dans une conférence en 2013 qui présente des concepts qui sont orthogonaux avec la genèse même de Java. Qu'en penser? Tout d'abord les unités de temps manipulées par THOMPSON sont le nombre de cycles d'horloge et les nano secondes, et il se réfère au nombre d'instructions assembleur exécutées par cycle pour apprécier la performance d'un programme. Je ne sais pas pour vous mais de mon côté, on me demande de m'intéresser à des problèmes de lenteur quand l'effet sur l'expérience utilisateur engendre des attentes de plusieurs secondes (voire minutes!). Du coup les invocations de méthode que je chasse affichent une durée de l'ordre de la centaine de milli secondes. Ces écarts énormes dans nos préoccupations respectives sont directement liés à la différence de nos univers: mon quotidien est l'informatique de gestion: un client léger, un serveur d'app, une base de données, des services web et les caches qui m'intéressent stockent des objets métiers et pas des octets (enfin pas directement). En gros des I/O, de la sérialisation, du parsing, des algos assez pauvres, bref énormément de tuyauterie plaçant mes préoccupations dans des sphères nettement moins exigeantes que les siennes. Mais merci à lui de nous rappeler cette réalité et de nous présenter des pistes d'optimisation à explorer quand toutes les évidences de haut niveau habituelles seront épuisées.


Au passage il nous fait profiter de son expérience en production avec le G1GC qui ne semble pas aussi prometteur que nous pouvions l'escompter, le poussant à revenir sur le CMS. On en apprend également sur les effets de l'immutabilité de la programmation fonctionnelle sur le GC et il n'hésite pas à nous balancer quelques Scuds en demandant pourquoi des fonctionnalités du langage telles que les lambdas représentent tant dans nos attentes quand il reste tellement à optimiser dans l'existant… Dès qu'elles seront disponibles dans Parleys, précipitez vous sur ses prestations.






Je termine ce billet en remerciant l'équipe organisatrice de la manifestation: l'ambiance est au rendez-vous, y en a pour tous et la soirée "meet and greet" (en observant la tête de quelques uns vendredi matin, ça aurait pu s'appeler "meet and drink" :o) ) est une super opportunité de rencontres et d'échange en mangeant du fromage. Vivement DevoxxFr 2014!



dimanche 6 janvier 2013

AngularJS + Play! Framework: Authentification





En tant que newbie sur Angular, je me suis posé la question de l'authentification dans ce type d'applications.

Pour ceux qui veulent aller directement à la présentation du code, c'est
là.



Depuis longtemps je suis habitué au développement de web apps dont les pages sont générées dynamiquement sur le serveur (JSP, JSF, PHP, etc.): cette problématique est donc comblée dans la plupart des cas par une redirection vers un formulaire d'authentification. Or avec un framework du type AngularJS, les pages sont générées dynamiquement sur le client à partir de templates nourries de données obtenues du serveur collectées grâce à du code client (Javasript).

D'un point de vue technique cette approche a évidemment énormément de sens, car:





  • Toutes les ressources clientes sont donc "cachables": templates, Javascript

  • A l'heure du Cloud (un buzzword, un), le coût d'hébergement est proportionnel à la sollicitation, il est tout naturel de transférer sur la machine du client (gratuite) toute charge éligilble

  • L'état du client est géré... sur le client (un truc de malade), permettant de réduire la pression sur la mémoire de la partie serveur (au point précédent on a économisé de la CPU, là on s'occupe de la RAM!). Sans compter que si la partie serveur ne maintient plus d'état, n'importe quelle instance pourra servir n'importe quelle requête... Nous parlons donc de conception Stateless (buzzword #2), permettant de déployer les noeuds en ayant aucun autre souci que la répartition de charge (pas de synchronisation entre les noeuds), m'amenant tout doucement vers le 3ème buzzword, la scalabilité horizontale.



En réfléchissant, si la traditionnelle redirection vers le formulaire de login ne semble pas être une option adaptée, que reste-t-il? Facile: le protocole HTTP prévoit au moins deux codes de retour liés aux problèmes de contrôles d'accès: 401, authentification requise, et 403, authentification refusée. Parfait, le premier m'explique que je dois présenter mes papiers et le second me signale que l'authentification fournie ne comprend pas l'accréditation nécessaire pour accéder à la ressource demandée.



Donc me voilà parti sur Google avec les mots clefs "Angular authentication 401" et je tombe sur un article fort intéressant:
http://www.espeo.pl/2012/02/26/authentication-in-angularjs-application . La démonstration est complète: toutes les requêtes tenues en échec suite à une erreur 401 sont bufferisées, en attente de la connexion de l'utilisateur et retentées le cas échéant. Et si on veut quelque chose de plus basique? Un peu plus newbie? Genre une redirection vers un formulaire de login à la première erreur 401 et une redirection a la racine suite à authentification? C'est sûrement pas aussi complet, mais l'aspect naïf permet de monter tranquillement en compétence sur AngularJS.



Avant toute chose, il nous faut un backend, mon choix c'est porté sur Play 2.1-RC1 car:



  • Il est stateless par essence

  • C'est hype, j'en avais envie et c'est moi le chef du blog (#noTroll)

Point de départ standard avec une application Play vide, ensuite on récupère une partie de l'authentification du sample
zentask en modifiant quelques aspects:



  • Tout d'abord, en cas de nécessité d'authentification, pas de redirection => 401:


  private def onUnauthorized(request: RequestHeader) = Results.Redirect(routes.Application.login)
devient:


  private def onUnauthorized(request: RequestHeader) = Results.Unauthorized





  • La démonstration nécessite une ressource protégée:




  def protectedResource = IsAuthenticated{
    username => _ =>
    Ok(Json.obj("test"->"1234"))
  }






  • Comme on veut faire une application cliente qui se connecte à un backend, pas d'utilisation des templates Play et modification de la route pour que la racine pointe sur une ressource statique:

GET     /                           controllers.Assets.at(path="/public", file="index.html")



Le code est disponible
ici.



Vérifications:





  • Pas autorisé:




$ curl http://localhost:9000/protectedResource -v
* About to connect() to localhost port 9000 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 9000 (#0)
> GET /protectedResource HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: localhost:9000
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Content-Length: 0
<
* Connection #0 to host localhost left intact
* Closing connection #0


L'application réfute bien l'accès avec un code 401.





  • Authentification:




$ curl http://localhost:9000/login -d 'mail=tony@stark.com&password=ironman' -v
* About to connect() to localhost port 9000 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 9000 (#0)
> POST /login HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: localhost:9000
> Accept: */*
> Content-Length: 36
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 36 out of 36 bytes
< HTTP/1.1 200 OK
< Set-Cookie: PLAY_SESSION=1701c43b7f845bdde0e38c0f43705d54b6815977-mail%3Atony%40stark.com; Path=/; HTTPOnly
< Content-Length: 0
<
* Connection #0 to host localhost left intact
* Closing connection #0

Code 200, un cookie signé de session en retour… tout va bien, donc on retente l'accès à la ressource protégée en présentant le sésame:




$ curl http://localhost:9000/protectedResource -b "PLAY_SESSION=1701c43b7f845bdde0e38c0f43705d54b6815977-mail%3Atony%40stark.com" -v
* About to connect() to localhost port 9000 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 9000 (#0)
> GET /protectedResource HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: localhost:9000
> Accept: */*
> Cookie: PLAY_SESSION=1701c43b7f845bdde0e38c0f43705d54b6815977-mail%3Atony%40stark.com
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Content-Length: 15
<
* Connection #0 to host localhost left intact
{"test":"1234"}* Closing connection #0


On obtient donnée attendue, authentification réussie!



Maintenant je m'attaque au client:




<html ng-app="angularAuth" authenticator>
<head>
  <title>Angular authent</title>
    <script type="text/javascript" src="/public/javascripts/angular/angular.min.js"></script>
    <script type="text/javascript" src="/public/javascripts/angular/angular-resource.min.js"></script>
    <script type="text/javascript" src="/public/javascripts/app.js"></script>
    <script type="text/javascript" src="/public/javascripts/controllers.js"></script>
</head>
<body>
<h1>Simple authentication example</h1>
<div ng-view></div>
</body>
</html>


Mon module AngularJS est sommaire:




angular.module("angularAuth",['authServiceProvider']).
    config(['$routeProvider',function($routeProvider){
        $routeProvider.
            when("/", {templateUrl:"public/partials/protectedContent.html", controller:ProtectedCtrl}).
            when("/login",{templateUrl:"public/partials/login.html", controller:LoginCtrl}).
            otherwise({redirectTo:"/"})
    }]).
    directive('authenticator',function($location){
        return function(scope, elem, attrs){
            scope.$on('event:auth-loginRequired',function(){
                $location.path("/login")
            })
        }
    })  ;



En gros, quand "/" est demandé, affichage du template tirant la ressource protégée et lorsque "/login" est demandé, affichage du formulaire de login et redirection dans tous les autres cas.

Ensuite un listener va être positionné afin de réagir à l'évènement de demande d'authentification. L'utilisation de la directive permet de le placer au niveau du module, soit une fois pour toutes. Ne pas oublier de mentionner la directive dans le fichier html (moi, j'ai cherché un moment au début :-D).



Le concept présenté par Witold Szczerba est de tirer parti de la possibilité de poser des intercepteurs sur le service $http, c'est ce que je vais faire mais de façon plus naïve dans le module "authServiceProvider" injecté dans "angularAuth":




angular.module('authServiceProvider', []).
config(['$httpProvider', function($httpProvider) {

$httpProvider.responseInterceptors.push(function($q,$rootScope,$log){
function success(response) {
// $log.info(response)
return response
}

function error(response) {
if (response.status === 401) {
$log.error("401!!!!")
$rootScope.$broadcast('event:auth-loginRequired')
}
return $q.reject(response)
}

return function(promise) {
return promise.then(success, error)
}

})

}])



La fonction: si une requête retourne une erreur 401, alors l'évènement de demande d'authentification est propagé et stimule ainsi la directive et le formulaire de login apparaît. Je vous épargne un couplet sur l'API Promise d'AngularJS et cous encourage à aller consulter le Reference Guide.



Les contrôleurs du
formulaire d'authentification, de récupération de la ressource protégée et les
templates associés sont spartiates et consultables sur GitHub.



En introduction, j'ai présenté les arguments liés à la rationalisation de l'infrastructure d'hébergement, en revanche à l'heure actuelle il est clair que la charge de développement est supérieure comparée à une application dans laquelle les vues sont générées par le serveur: on y déclare simplement l'emplacement du formulaire de login.



La démo est testable sur
Heroku.