Bilan 2013 et Objectif 2014… Qu’ai-je appris cette année ?

Nous sommes en 2014, et j’aime bien faire un petit bilan professionnel de l’année passée. Qu’ai-je appris ? Aurais-pu faire plus ? Me suis-je amusé ?

Du Classic

J’ai commencé 2013 par ce qu’on appelle communément « un grand compte », avec  un projet Titanesque. Je ne rentrerai pas dans les détails, mais sur le contenu, j’ai eu droit à de l’Oracle / Hibernate, Spring, des pages et des pages de formulaire, le tout porté par un bon gros Liferay. Et tout ça était relié à plein d’autres applications du même genre, à travers des Web Services SOAP. résultat22693-le-plat-de-spaghettis   De la frustration, mais des technos solides qu’il est bon de maitriser, dans une ambiance positive avec quelques personnes avec qui j’ai pris plaisir à travailler.

De la Mobilité

Changement de registre. Un client arrive, avec un besoin un peu flou, et peu d’argent (en gros un mois de développement). « Je veux un site web, une application mobile, Android, iOs, stocker des photos, scanner des choses, gérer des données de référence, des droits d’accès, etc… Carte blanche sur la techno employée ». Ah. En 20 jours, donc… Et bien cela m’a permis de bien m’amuser :-). Et une mission comme celle-là, c’est une formation accélérée pour n’importe qui ! L’objectif étant d’avoir très rapidement une usine de développement, une application web et une API pour communiquer avec mes applications mobiles, j’ai choisi des technos que je savais adaptées, sans obstacle pour moi. Bref, à la fin de la première matinée, j’avais mon application sur Github, le hook Cloudbees / Jenkins qui va bien avec mon déploiement sur Google AppEngine. Une dépendance Maven vers Jersey, et j’aurais mon API sans soucis au fur et à mesure de mon développement. L’API, un jeu d’enfant. Un coup de Twitter Bootstrap et AngularJS pour le front, et ça irait tout seul. Mais même avec la meilleure volonté du monde, comment produire ces deux applications mobiles dans le temps imparti ? Nous sommes partis sur la solution Apache Cordova, couplé à JQuery Mobile pour le thème et éviter de se poser des questions. Pour des raisons fonctionnelles, nous avons aussi utilisé AngularJS côté mobile, ce qui devait nous simplifier la vie, et ce choix a été payant. Heureusement que nous n’avions pas Windows Phone en cible, la stack choisie n’aurait pas fonctionné. Bref, je me suis éclaté ! On apprend à coder vite, à s’appuyer sur des choses fiables, à s’adapter très très vite quand on rencontre un problème (aaaahhh les plugins Cordova… *soupir*), et on écarquille les yeux quand on se rend compte à quel point on peut produire vite, sans contrainte.

Mes coups de coeur :

cordova            appengine

(Oui, Cordova est quand même très chouette, malgré si l’on entend que c’est l’application mobile du pauvre…)
(Et oui, on y a passé un chouilla plus de temps que prévu 😉 )

Du WEB

On enchaîne avec une mission pure WEB… Environnement Google AppEngine, un besoin simple, mais on passera un peu plus de temps sur le design. AngularJS est alors incontournable, j’essaye de m’y intéresser plus, de penser aux directives, aux bonnes pratiques… Autant la courbe d’apprentissage est très rapide pour les besoins primaires, autant je trouve que ça se complique aussi très vite dès que l’on pense « composant ».
Mais clairement, ça aurait été difficile de passer l’année 2013 sans y toucher.angularjs

De l’Intégration

Oui, des EIP : Enterprise Integration Patterns. Je ne pensais pas compléter ma panoplie de développeurs par ce domaine, mais certaines opportunités m’y ont amené, sans que je ne le regrette le moins du monde !
L’intégration de données peut paraître moins sexy. Pourtant, en quelques mois j’ai croisé de vraies problématiques importantes, formatrices ! On pensera fiabilité, performance… On s’adapte aux contraintes systèmes, on se devra d’être flexible, on découvre de nouveaux patterns, et on pensera un peu différemment.

Mon nouvel ami : apache-camel-logo

De l’Associatif

En 2013, j’ai encore rencontré plein de gens vraiment passionnants et passionnés. J’ai assisté à des JUGs, à des meetup, j’ai assisté à Devoxx France, et j’ai même eu la chance d’être speaker au Jug Summer Camp.
Grâce à l’équipe du Google Developer Group Paris, j’ai aussi pu m’impliquer un peu plus dans l’organisation de plusieurs soirées, pour des technos et une communauté que j’apprécie.
Je ne suis resté qu’à peine deux ans à Paris, mais je pense ne pas avoir perdu mon temps sur place… Merci à toutes les personnes qui m’ont appris autant, c’était vraiment, vraiment bien.

Et maintenant ?

Et 2014, c’est Lille ! Je sens qu’ici aussi il y a des choses à faire. Un Chti Jug est actif, un ChtiJS aussi, et j’ai moi-même quelques ambitions.

Autour des technos Google, il y aura toujours des choses à faire, et des gens à rencontrer ! J’en ai profité pour créer deux choses :
– le Meetup GDG Lille : www.meetup.com/GDG-Lille/
– Le Twitter qui va avec : https://twitter.com/GDGLille/
Les premières soirées vont arriver courant février ! N’hésitez pas à me contacter si vous avez des envies ou des besoins.

J’ai aussi une liste de technos auxquels j’ai envie de m’intéresser de plus prêt :
Docker
Dart
– Java 8
– suivre encore et toujours le monde Javascript, en pleine effervescence…

Et vous, avez-vous ciblé vos technos de 2014 ?

[CloudBees] Déployer sur Google App Engine avec le même numéro de version que dans le Pom.xml Maven

cloudbees-logo

Connaissez-vous CloudBees ? C’est un outil super (Une de ses fonctionnalités, les ClickStart, présentée ICI), qui est dans la mouvance des PaaS, et qui a la particularité de proposer un service qu’ils appellent « Dev@Cloud ». Concrètement qu’est ce que c’est ? Un repository Git privé, un Jenkins rien que pour nous, qui nous permet de builder, ou de déployer nos projets Java ou NodeJS sur leur partie « Run@Cloud » (concrètement des instances Amazon). Bref, CloudBees fournit une usine de développement pour de l’intégration continue. (Nous pouvons bien entendu brancher notre Jenkins vers n’importe quel repository git, genre Github).

Depuis quelques temps, CloudBees permet de déployer aussi sur Google App Engine, et c’est à cette fonctionnalité que nous allons nous intéresser.

Une fois que nous nous sommes authentifiés à travers https://appengine.cloudbees.com/index.html, il suffit de suivre le workflow pour déployer son application immédiatement.

Configuration Jenkins

Allons voir ce qui se passe, et comment Jenkins déploie sur Google App Engine.
Un plugin est là, en post-build, pour faire le boulot.

jenkins-appengine

Le Besoin

Nous voyons que nous pouvons surcharger le numéro de version de l’application. Par défaut dans la configuration CloudBees, le numero de version est surchargé par le numéro de build. C’est à dire qu’à chaque fois que l’on build son application, une nouvelle version est déployée sur Google App Engine. Bon, pourquoi pas…

Mais nous avons un POM.xml qui contient déjà un numéro de version du projet. Comment l’utiliser ?

Solution

Première étape : enlevons la surcharge faite par Jenkins (cf capture d’écran). Dans ce cas-là, c’est le numéro de version contenu dans le fichier appengine-web.xml qui sera utilisé.

<application>monapplication</application>
    <version>${appengine.app.version}</version>
    <threadsafe>true</threadsafe>
</appengine-web-app>

Au moment du build Maven, nous remplissons automatiquement la variable appengine.app.version avec le numéro de version du projet. Pour ce faire, dans le POM.xml, nous définissons simplement:

<properties>
    <appengine.app.version>${project.version}</appengine.app.version>
    <appengine.target.version>1.8.1</appengine.target.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

Dans l’idée, ça devrait fonctionner.

Problème : Google App Engine n’accepte ni les majuscules, ni les « point » dans ses numéros de version. Autant dire que 1.0.0-SNAPSHOT ne colle pas trop à la spécification 🙂
https://developers.google.com/appengine/docs/java/config/appconfig?hl=fr )

Solution : Utilisation du plugin maven gmaven-pugin, dans la phase « Initialize », pour changer un peu le numéro de version afin qu’il soit accepté par Google App Engine.

<plugin>
    <groupId>org.codehaus.gmaven</groupId>
    <artifactId>gmaven-plugin</artifactId>
    <version>1.5</version>
    <executions>
        <execution>
            <!--<id>properties</id>-->
            <phase>initialize</phase>
            <goals>
                <goal>execute</goal>
            </goals>
            <configuration>
                <source>
                    <!-- version pattern : 1.0.2-snapshot -->
                    project.properties["appengine.app.version"] = project.version.replace(".","-").toLowerCase()
                </source>
            </configuration>
        </execution>
    </executions>
 </plugin>

On remplace les point par des tirets, le tout en minuscule et nous voilà App Engine Compliant.

Conclusion

Maven est tout à fait capable de gérer différents profils, des configurations, et il est de notre intéret de garder cette logique pour gérer son versioning. Un petit plugin muni d’un script Groovy pourra nous aider à passer quelques obstacles simplement.

LB.

Rechargement à chaud et Développement Google App Engine / Maven

appengine mavenGoogle App Engine est une plateforme vraiment sympa. En plus d’être multi-langage (Python, Java, Go et Php), App Engine fournit tout un tas de services appréciables, tels qu’un DataStore intégré, un BlobStore, une gestion de Cache, un service d’envoi de mail et j’en passe… Retrouvez la liste complète ici : https://developers.google.com/appengine/docs/java/apis

Bref, C’est un PAAS complet et performant, qui a fait ses preuves en production.

Mais parlons maintenant de confort de développement.

Je suis développeur Java, et j’essaye autant que possible d’avoir des projets standardisés autour d’un outil de build, au hasard Maven. A priori, tout va bien, Google fournit le plugin qui va bien. Si l’on suit les instructions et que l’on construit correctement son projet, tout devrait bien se passer. Plus qu’à lancer en local mon serveur et ses services associés :

mvn appengine:devserver

Mon projet se build, mon serveur se lance, ma jolie page HTML s’affiche, je suis content !

Habitude oblige, je laisse mon serveur tourner et je commence à modifier mes pages HTML. Sauvegarde, F5, et……. rien. Ma page n’est pas actualisée. Pourquoi ? Et bien le serveur App Engine qui est lancé se base sur votre dossier target généré par Maven. Et sans nouveau build, aucune raison que ce dossier n’évolue.

Alors comment faire pour profiter des fonctionnalités App Engine (datastore par exemple) en local, tout en pouvant développer son Front-End confortablement ?

L’objectif est d’arriver à découpler le Front et le Back End… Le serveur App Engine, qui contient les fonctionnalités du back-end qui nous intéressent, pourra être lancé une fois à l’aide de Maven, disons sur le port 8000. Pour configurer le port, il suffit de changer votre POM :

<plugin>
   <groupId>com.google.appengine</groupId>
   <artifactId>appengine-maven-plugin</artifactId>
   <version>${appengine.target.version}</version>
   <configuration>
     <port>8000</port>
   </configuration>
 </plugin>

Maintenant, nous allons ajouter un serveur qui nous servira le front, par exemple Jetty. Hop, on alimente le POM.xml avec le plugin qui va bien :

<plugin>
   <groupId>org.eclipse.jetty</groupId>
   <artifactId>jetty-maven-plugin</artifactId>
   <version>9.0.3.v20130506</version>
 </plugin>

On lance notre Jetty (qui lui se lancera sur le port 8080)

mvn jetty:run

On ouvre notre navigateur favori, on va sur localhost:8080 pour attaquer notre Jetty et si tout s’est bien passé, le site apparaît… On modifie l’index.html (par exemple), on sauvegarde, F5 sur le navigateur, et la modification est bien prise en compte, ouf !

Problématique : à un moment, votre front va vouloir parler au back, par exemple à travers une requête REST, L’objectif est donc d’appeler son serveur App Engine, qui se trouve sur un autre port. On fait un petit Hack dans son code Javascript pour appeler la bonne URL, on lance sa requête, et…. Erreur dans le navigateur, Requête Cross Domain non autorisée. Et oui, un navigateur ne lance pas de requêtes vers un autre site, question de sécurité ! Pour Chrome, il existe une solution simple, le lancer avec l’option

--disable-web-security

Mais ce n’est pas l’idéal. Pourquoi ? D’abord parce que cela compromet votre navigateur si vous l’utilisez pour vous balader sur le net. La seconde raison est que de toute façon ça vous oblige à avoir un petit hack dans votre code côté client pour faire pointer vos requêtes vers le bon port.

La Solution ? Apache 2 et un Reverse Proxy

Alors comment faire ? Ma solution est d’avoir un troisième serveur, en frontal, qui va décider vers qui envoyer vos requêtes vers App Engine ou Jetty. Pour ma part j’ai choisi Apache2 et son module Proxy / Reverse Proxy qui fait ça très bien. (Documentation officielle : http://httpd.apache.org/docs/current/mod/mod_proxy.html )

Pour résumer ma configuration Apache 2 : Un fichier apache2.conf qui écoutera le port 80

Listen 80

Et la définition d’un site (il faudra avoir chargé les modules adequat auparavant, cf documentation officielle) :

<VirtualHost localhost:80>
   ServerAdmin webmaster@localhost
   ServerName localhost

   ProxyRequests Off
   ProxyVia Off

   ProxyPass /_ah http://localhost:8000/_ah
   ProxyPassReverse /_ah http://localhost:8000/_ah

   ProxyPass / http://localhost:8080/ 
   ProxyPassReverse / http://localhost:8080/
</VirtualHost>

Maintenant, quand avec mon navigateur je vais sur http://localhost/, Je sais que toutes mes requêtes REST qui sont préfixées par « _ah » sont redirigées vers App Engine sur le port 8000 par le reverse proxy, le reste allant vers Jetty.

Mission accomplie 🙂

Conclusion

On résume.
J’ai un Apache frontal qui dispatch mes requêtes vers Jetty ou App Engine en filtrant les URL appelés grâce à un Reverse Proxy.

Maven Apache frontal

OK, j’entends d’ici la critique : il faut vraiment lancer 3 serveurs différents pour pouvoir développer confortablement un simple site Web hébergé sur App Engine ? Prenons le temps de relativiser, et intégrons le fait qu’App Engine transporte avec lui sa persistence, c’est déjà un service d’économisé.

Dans mon exemple, j’aurais pu aussi éviter de devoir lancer Jetty. En effet, si mon front-end est 100% statique, aucune JSP à compiler ni rien, je pourrais demander à Apache de me restituer directement mes fichiers statiques en configurant un Directory qui pointe vers mon projet dans le VirtualHost. Qui plus, mon Apache est démarré comme service, et une fois lancé il est fait pour être oublié !

Passer une heure à configurer tout ça est un sacrifice que je referai tant les services rendus sont appréciables, le résultat étant un projet buildable, intégrable dans une usine de développement continu, testable et facilement déployable dans un environnement puissant.

LB.