All posts in Java

LRA Long Running Actions

Principe général

Long Running Actions (LRA) est un module de la stack Eclipse MicroProfile comme peuvent l’être « Health », « Fault Tolerance » ou « GraphQL ». Son objectif est de permettre la coordination des microservices concourant à implémenter une même activité métier. Sur le plan théorique ce pattern est référencé sous le nom de SAGA.

Bien sûr l’idée n’est pas de revenir au mode de fonctionnement centralisé et fortement couplé dont l’architecture microservices essaie de s’éloigner. Il n’est donc pas question d’opérer des transactions SQL distribuées comme on a pu le faire il y a quelques années, chaque microservice reste seul responsable de son système de stockage qui n’est pas partagé.

Le but ici est d’atteindre l’eventual consistency. Attention pour ceux qui ne maîtriseraient pas l’anglais, eventual est un faux amis, il ne s’agit pas de dire que le système sera éventuellement cohérent mais qu’il le sera forcément tôt ou tard.
Ce concept est familier aux utilisateurs des bases de données de nouvelle génération qui l’exploitent pour offrir une bonne montée en charge.

Examinons maintenant plus concrètement comment déployer cela au sein d’une architecture microservices.

Le coordinateur

L’implémentation de Long Running Actions requière la coopération d’un service additionnel à nos microservices métier. Son rôle sera d’orchestrer les transactions, c’est à dire d’informer nos services pour leur demander de compenser (défaire) leurs actions ou au contraire de les valider définitivement.

Ainsi la première étape consiste à lancer ce fameux coordinateur. Nous utiliserons ici l’implémentation issue du projet Narayana, packagée dans un microservice Quarkus:
docker run -d -p 8080:8080 quay.io/jbosstm/lra-coordinator

Pour vérifier qu’il tourne correctement:
curl -i localhost:8080/lra-coordinator
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
content-length: 2
Narayana-LRA-API-version: 1.1

[]

D’autres alternatives à Narayana existent et il est possible de les utiliser sans impact sur le reste de notre architecture car les interactions s’appuient sur un protocole HTTP REST normalisé.

Sur les microservices

Au niveau du code de nos microservices, les _endpoints_ participant à une transaction métier longue doivent être annotés @LRA, par exemple:

@LRA(value = LRA.Type.REQUIRED, end=false)
@POST
@Consumes(MediaType.TEXT_PLAIN)
@Path("/book")
public Response bookFlight(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) String lraId, String destination) {
  if (destination.equals("Toulouse") || destination.equals("Paris")) {
    System.out.println("Succès");
    return Response.ok().build();
  }
  else {
    System.out.println("Echec");
    return Response.serverError().build();
  }
}

L’annotation @LRA présente des similitudes avec une autre annotation largement utilisée : @Transactional. En effet, elles partagent toutes deux des paramètres pour spécifier le périmètre de la transaction, qui se ressemblent beaucoup. Par défaut, l’attribut value est égal à « REQUIRED », ce qui indique que si une transaction est déjà en cours, la méthode sera exécutée dans son contexte. La propagation de l’id de la LRA se fait au travers de l’entête HTTP « Long-Running-Action ». C’est ainsi la présence de cette information dans la requête entrante qui détermine s’il faut créer une LRA ou pas. Dans la réponse HTTP nous retrouverons également cette entête. Elle devra être réutilisée par le client dans les requêtes successives. Pour fixer les idées la valeur de cette entête pourrait être par exemple :

http://localhost:8080/lra-coordinator/0_ffffc0c5100f_f355_6113bebe_22

L’id de la LRA prend la forme de son URL canonique. La création de la LRA se fait sur demande par l’appel de l’API REST du coordinateur depuis notre microservice.
Nous n’avons pas à coder cette interaction, cela se fait automatiquement par la librairie LRA.
Les appels aux microservices suivants, lorsque ceux-ci sont annotés avec @LRA et que l’entête est bien fournie, se voient donc inclus dans la même transaction tant que la propriété end=true n’est pas fixée. Quand ce sera le cas, la transaction LRA sera fermée après l’exécution de la méthode et le coordinateur appellera pour chaque microservice son point de terminaison d’API annoté @Complete.

@Complete
@Path("/complete")
@PUT
public Response completeFlight(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) String lraId, String userData) {
  String message = "Flight Booking completed with LRA with id: " + lraId;
  System.out.println(message);
  return Response.ok(ParticipantStatus.Completed.name()).build();
}

Si au contraire, une des méthodes des microservices annotées @LRA avait été en erreur, la LRA dans son ensemble aurait été annulée. Les méthodes callback invoquées auraient alors été celles annotées @Compensate.

@Compensate
@Path("/compensate")
@PUT
public Response compensateFlight(@HeaderParam(LRA_HTTP_CONTEXT_HEADER) String lraId, String userData) {
  String message = "Flight Booking compensated with LRA with id: " + lraId;
  System.out.println(message);
  return Response.ok(ParticipantStatus.Compensated.name()).build();
}

Conclusion

Comme nous venons de le voir, le module Long Running Actions fournit un cadre d’implémentation du pattern SAGA.
Si des points communs avec les transactions JPA (Java Persistence API) peuvent être relevés, le fonctionnement des LRAs est cependant largement plus découplé et repose sur un système de compensation. C’est en effet à nous d’implémenter le rollback en fonction bien sûr de la technologie sous-jacente. Même principe pour la méthode @Complete c’est à nous qu’incombe de coder la logique de « commit« . Ce terme est à considérer avec des guillemets car même si le système de stockage du microservice est construit sur une base traditionnelle, sa transaction SQL locale sera déjà véritablement commitée (il est inenvisageable de conserver des verrous base de données sur plusieurs requêtes HTTP). La plupart du temps la tâche de la méthode @Complete se résume à nettoyer les ressources ou informations conservées dans l’optique de pouvoir compenser la LRA si finalement elle devait être annulée.

Ainsi l’essentiel du framework consiste à mettre en œuvre une série de notifications pour informer les microservices des résultats des opérations des uns des autres. Cette synchronisation se fait avec un décalage qui peut être plus ou moins long, certains microservices pouvant échouer à compenser, mais le coordinateur insistera et les notifiera à nouveau. L’objectif final n’étant pas de garantir une consistence instantanée des données mais juste de permettre d’y arriver à un moment donnée.

Pour plus de détails encore dans le protocole Long Running Actions, voici sa javadoc, bien sûr n’hésitez pas à expérimenter avec Quarkus par exemple:
https://download.eclipse.org/microprofile/microprofile-lra-2.0/apidocs/

Quelles perspectives pour Java et le développement Mobile ?

Quelles perspectives pour Java et le développement Mobile ?

C’est la question posée aux intervenants et participants de notre dernier ApéroTech du 14 novembre dernier à Toulouse.

A la découverte de Flutter 

Pour lancer l’ApéroTech sur le sujet du futur du développement Mobile, Thibaud a présenté une alternative à React Native : Flutter, lancé par Google. Les participants ont ensuite pu bénéficier d’une démo en live de l’API Spatioport pour découvrir les capacités du framework.

Retour d’experiences croisées sur Oracle Code One 2019

L’ApéroTech s’est poursuivi avec l’intervention d’Olivier et Bertrand, heureux participants du dernier Oracle Code One à San Francisco qui ont fait le point sur l’avenir de l’écosystème Java.
JVM, GraalVM, JakartaEE, Microprofile et Kubernetes : de multiples bouleversements accompagnent les mutations des environnements d’exécution.
Les impressions à chaud de Bertrand sont à retrouver sur son article ici.

Merci aux intervenants et participants pour leurs échanges et leur belle énergie !

Nous avons hâte de vous retrouver en mars 2020 pour une nouvelle édition.

Informations et inscriptions sur la page Meetup Les Z’ApéroTech.

Quarkus : le framework Cloud Native révolutionnaire

L’écosystème Java est en plein renouveau. Oracle a officiellement acté son désengagement de Java EE (renommé Jakarta EE), les spécifications et leur implémentation de référence se font désormais sous l’égide de la fondation Eclipse et non plus au JCP (Java Community Process). Si ce chamboulement a pu générer quelques craintes et appréhensions quant au futur de la plateforme, aujourd’hui les conditions de passation de témoin entre Oracle et Eclipse semblent dorénavant établies (voir ici pour plus de détails sur l’imbroglio au sujet de l’utilisation du nom de package javax).

Place donc à la technique et je dois dire, pour vivre les choses de l’intérieur (nous sommes membres du consortium Jakarta) que la dynamique Jakarta est bien réelle. Le tournant micro-service a été pris avec conviction (il était temps), l’axe Cloud Native est clairement une priorité pour le consortium.

Jakarta poursuit l’oeuvre de standardisation de Java EE et offre aux développeurs le choix de l’implémentation. Nous avons toujours la filière traditionnelle avec un modèle basé sur le serveur d’applications. Mais surtout nous avons désormais la déclinaison Microprofile du standard. L’application ne nécessite alors plus de serveur pour fonctionner mais est packagée sous la forme d’une application autonome taillée pour les containers Dockers et les clusters Kubernetes. L’approche prise par la spécification Microprofile est particulièrement intéressante : conserver tels quels les modules Jakarta EE (CDI, JAX-RS, JPA…) et y adjoindre de nouveaux composants dédiés aux nouvelles problématiques découlant des architectures microservices. Notamment sont couverts les sujets liés à la tolérance à la panne, l’authentification par token JWT, la documentation Open API, les métriques et les traces, le Health Check, la génération de clients REST, l’intégration aux services de messaging… Bien sûr pour chacun de ces thèmes, il y a d’un côté la spécification des API et de l’autres les implémentations.

Cela nous amène à Quarkus qui est la nouvelle proposition Microprofile de Red Hat. Je dis nouvelle parce qu’il y a déjà Thorntail qui est la déclinaison Microprofile du serveur d’application WildFly. Quarkus lui, est une réécriture pensée véritablement pour l’approche Cloud Native. En effet, l’objectif ultime de Quarkus est de permettre la compilation native des applications grâce à GraalVM et ainsi corriger les deux faiblesses historiques de Java que sont l’empreinte mémoire et le temps de démarrage. A une époque pas si lointaine où le modèle d’exécution était le gros serveur d’applications pas ou peu redondé qui devait être redémarré le moins souvent possible, ces deux lacunes posaient peu de problème. Aujourd’hui le paradigme a changé, les applications sont découpées en plusieurs unités d’exécution (microservices) qui sont démarrées, répliquées, déplacées sur un cluster Kubernetes de nombreuses fois par jour (potentiellement tout du moins). Il est ainsi crucial que nos processus soient faiblement gourmands en ressources et puissent être lancés juste en une fraction de seconde.

Quarkus est encore jeune, la compilation native échoue plus souvent qu’elle ne réussit, mais ce n’est pas bloquant, il suffit alors de se rabattre sur une exécution classique JVM qui reste bien plus performante que n’importe quel serveur d’applications ou que Thorntail. Quarkus nous montre le futur des applications Java d’entreprise orientées Cloud Native. Si vous êtes intéressés, n’hésitez pas à échanger avec nous ou à vous inscrire à une de nos sessions de formation.

 

IoT et Agriculture, SAFe et les secrets de JakartaEE8

Une nouvelle édition des ApéroTech a réuni il y a quelques jours une trentaine de passionnés de technologie dans les locaux de DocDoku à Toulouse.

IoT, méthodologie projet et programmation ont été les thèmes choisis et présentés par des intervenants particulièrement enthousiastes (et ce, alors que la partie Apéro n’avait pas encore commencé 😉 )

Les participants ont ainsi pu découvrir et échanger sur :

IoT : à la découverte d’une sonde connectée dernière génération.

Junior a immergé les participants dans la conception et le fonctionnement d’un device et de sa plateforme associée. Conçue en collaboration avec des agriculteurs pour connaître les besoins des sols en fonction des plantes cultivées, le projet présenté utilisait les technologies bluetooth4.0, Lorawan, Objenious, REST, PostgreSQL et Rails.

L’agilité à l’échelle de l’entreprise avec SAFe.

Bertrand a donné aux participants les clés de cette méthodologie, ses avantages, dans quels contextes l’utiliser sans toutefois oublier ses limites.

Les nouveautés de la plateforme #JavaEE ou plutôt #JakartaEE 8 .

Florent a fait le point sur les grandes familles de nouveautés à retrouver dans cette nouvelle plateforme : l’alignement entre modules, les nouveaux standards Web, les nouveaux modules…

Le prochain ApéroTech aura lieu le jeudi 18 avril à Paris.
Renseignez-vous et téléchargez votre invitation gratuite.

Les Feature Toggles* : Activer / Désactiver dynamiquement une fonctionnalité d’un logiciel

* La désignation ne fait pas consensus et la liste des termes synonymes est très longue : Feature Flag, Feature Switch, Conditional Feature, Feature flipper, Feature Bits, Gatekeepers….

Le principe

À la livraison d’une nouvelle version d’un logiciel sur un environnement, toutes les nouvelles fonctionnalités sont rendues disponibles immédiatement. Au contraire, le modèle de design Feature Toggle* a pour but de fournir un interrupteur de fonctionnalités qui active ou désactive une partie du code sans nécessiter ni redéploiement ni redémarrage de l’application.

Les usages possibles

Cette fonctionnalité peut avoir de nombreux usages. Les cas suivants en sont un exemple et ne représentent pas l’exhaustivité des situations.

CAS 1 – Différents besoins sur différents environnements

Pratiquer des livraisons régulières, fréquentes et de petite taille est une des conditions à garantir pour l’agilité d’un projet (Continuous Delivery). L’enjeu est le maintien d’un cycle de développement court pour limiter les risques du rythme élevé de changements. Or si cette stratégie s’avère un atout en environnement de recette, où la validation de petites briques logicielles réduit la durée de la phase de tests, elle peut être difficile à réaliser en environnement de production. En effet, une fonctionnalité peut représenter plusieurs itérations de développements et il serait incongru de la mettre à disposition de l’utilisateur de façon incomplète. Le système de feature toggles rend possible la livraison de parties de fonctionnalités en mode désactivé sans que cela n’affecte la stabilité du code. L’activation pourra être réalisée au bout de quelques semaines, une fois que l’ensemble du code nécessaire aura été livré.

CAS 2 – Incident suite à une livraison

Lorsqu’un dysfonctionnement est rencontré en production par un utilisateur suite à une récente livraison, il sera possible de désactiver la fonctionnalité pour réduire l’instabilité du logiciel en attendant une résolution.

CAS 3 – Dépendances entre équipes

Il n’est pas rare que plusieurs équipes travaillent en parallèle sur des besoins différents et dans des délais qui leur sont propres tout en ayant en commun une ou plusieurs applications. Par exemple, l’interface peut être la même pour toutes les équipes. Lorsque le moment est venu pour une équipe de livrer son travail, elle se trouve gênée par les développements encore en cours ou en validation des autres équipes sur l’application partagée. Si chaque équipe a mis en place des toggles,  la livraison sera envisageable à la condition que chaque fonctionnalité non encore terminée soit désactivée.

CAS 4 – Tests comparatifs

Il existe une catégorie de Feature toggles dont l’activation se fait par utilisateur. La condition d’activation peut être déterminée par un profil de permissions ou encore l’appartenance à un échantillon. Au lieu de plusieurs environnements, un seul est nécessaire pour comparer des résultats entre différents groupe d’utilisateurs et valider une approche.

AUTRES CAS – L’activation de fonctionnalités peut aussi…

  • concerner la configuration d’un système opérationnel déjà en service afin de déterminer les meilleurs paramètres (court terme) ou bien de maintenir un service stratégique au détriment d’un autre en dégradant les performances à son profit (long terme)
  • être amenée à rester sur le long terme dans le cas du besoin de customisation de fonctionnalités par utilisateur (par exemple un mode « utilisateur premium»)

Selon Martin Fowler 1 – son blog, il existe deux axes de qualification pour un feature toggle, son dynamisme (changements au déploiement / à chaud / par requête) et sa longévité (nombre de jours / mois / années). Cette classification doit orienter vers le choix d’une implémentation.

Un rapide aperçu avec FF4J

FF4J  (Feature Flipping for Java) est un framework en licence libre apache 2.

Une fois les dépendances nécessaires ajoutées (ff4j-core, junit, ff4j-web) et la configuration paramétrée, il faudra créer un service fournissant une instance de la classe FF4J.

Étape 1. Créer un feature toggle

Cela consiste à insérer une nouvelle entrée dans un feature store (le système de stockage) précisant l’identifiant du toggle, sa description, son statut d’activation, son groupe d’appartenance, les rôles d’utilisateurs ou les stratégies associés. L’offre de système de stockage des données est large : mémoire, bases relationnelles ou no-sql.

CREATE TABLE FF4J_FEATURES (
  "FEAT_UID"            VARCHAR(100),
  "ENABLE"              INTEGER NOT NULL,
  "DESCRIPTION"         VARCHAR(1000),
  "STRATEGY"            VARCHAR(1000),
  "EXPRESSION"      VARCHAR(255),
  "GROUPNAME"           VARCHAR(100),
  PRIMARY KEY("FEAT_UID")
);

ci-dessus : Table prévue pour le stockage en base relationnelle, le champ « enable » stocke 1 pour le statut « activé » 0 pour « désactivé ».

Étape 2. Utiliser le feature toggle dans le code

L’identifiant choisi à l’étape 1 permettra de vérifier l’état d’activation.

If (ff4j.check("id.du.toggle")) {
	doBehiavorA()
}  else {
	doBehiavorB()
}

ci-dessus : si le toggle est activé alors le comportement A est joué sinon le comportement B fonctionne.

Étape 3 . Déployer le code sur un environnement

Étape 4 . Contrôler l’activation via la console d’administration

ci -dessus : Une interface graphique permet de réaliser l’opération sans nécessiter de compétences techniques.

Limites

     Ce mécanisme complexifie le code : deux cas de comportements sont implémentés en même temps donc deux fois plus de code. Il est donc conseillé de réfléchir aux bons emplacements stratégiques dans le code et de limiter le nombre de recours. Dans le même ordre d’idée, le nombre total de fonctionnalités couvertes se doit de rester faible pour rester maintenable.
     Heureusement, ce risque est diminué dans la plupart des usages puisqu’ils répondent à un besoin temporaire. Néanmoins, cette situation temporaire va induire une opération supplémentaire de nettoyage du code, une fois que la fonctionnalité est activée de manière définitive.
     Il existe également quelques cas où la sécurisation avec un toggle n’est pas envisageable. J’ai notamment déjà rencontré le cas lors d’un changement structurel important au niveau du modèle en projet .
     Il existe une controverse. En effet, les outils de gestion de versions (tel que Git) apportent une aide précieuse dans la résolution de certaines problématiques (ex. CAS 3). Si la pratique très courante du Feature Branching (séparation des fonctionnalités en branches) est jugée inadaptée face au défi de l’intégration et de la livraison continues pour les uns 1 – martin fowler blog, elle reste une réponse possible lorsque bien exécutée pour d’autres 2 – james mckay blog. Ces approches peuvent aussi être utilisées côte à côte.

     Enfin, cette approche va de pair et prendra tout son sens dans un contexte où l’automatisation des tests et des déploiements est déjà en place.

Quelques implémentations

Flaggr (Android), angular-feature-flags (Angular), rollout.io (javascript), Togglz (Java), au sein du framework Spring (Java)…

 

Retour sur EclipseCon France 2018

En septembre 2017, Oracle annonçait sa décision, en accord avec les autres grands acteurs du marché que sont IBM et RedHat, de transférer les technologies JavaEE à la fondation Eclipse pour «rendre le processus d’évolution de ces standards plus agile» [4].
Cette annonce a provoqué un séisme au sein de la communauté Java et a levé de grandes interrogations sur l’avenir de la plateforme, sur le positionnement du projet Eclipse MicroProfile et sur l’état d’avancement de cette transition.
Comme chaque année DocDoku1 était présent à l’EclipseCon France 2018, rendez-vous annuel de la communauté Eclipse à Toulouse.
Comme à chaque fois un thème est à l’honneur. Cette année il était légitime que ce soit le tour de la plateforme «entreprise» pour Java d’être sous le feu des projecteurs.
Étant moi même à l’affût d’information sur l’avenir de cette plateforme, j’ai profité de l’unique journée à laquelle j’ai pu venir, pour me concentrer sur JakartaEE et MicroProfile.

JakartaEE

JakartaEE


Au début de cette année, la communauté a choisi le nom JakartaEE pour désigner ce qu’Oracle appelait JavaEE. En effet Oracle a souhaité conserver ses droits sur la marque Java, il fallait donc trouver un autre nom.
Pourtant à la fin de l’année 2017 la fondation Eclipse avait annoncé la création du projet Eclipse Enterprise for Java (EE4J).

EE4J ou JakartaEE ?

Eclipse Enterprise for Java [5] est le projet «chapeau» pour tout ce qui concerne les technologies JavaEE, c’est à dire les API mais aussi les implémentations de référence transférées aussi par Oracle.
Eclipse JakartaEE Platform [6] est donc un sous-projet de EE4J qui reprend ce qu’était la spécifiaction de la plate-forme JavaEE : la définition d’un environnement d’exécution résultant de l’agrégation d’un ensemble spécifications d’API.
On trouve naturellement par ailleurs un sous-projet pour chaque API (Servlet, EJB, …) mais aussi les implémentations de références développées au sein de la fondation Eclipse ou par Oracle comme Yasson, EclipseLink, Glassfish, Grizzly, Jersey, …

Où en est la transition ?

Tout d’abord la procédure de transfert est longue car Oracle doit faire des vérifications (propriété intellectuelle, licence, …) pour chaque élément transféré.
En outre, les CTS2/TCK3 d’Oracle ne sont pas libres.
Nous apprenons que la transition se fera en plusieurs étapes :

  • Rendre JakartaEE 8 officiellement compatible avec JavaEE 8.C’est à dire obtenir une implémentation de référence JakartaEE qui passe les CTS/TCK actuels d’Oracle.
  • Fournir des CTS/TCK libres pour JakartaEE et s’assurer que l’implémentation de référence JakartaEE passe avec succès ces tests.
  • Une fois ces deux objectifs atteints JakartaEE pourra évoluer selon le processus normal de la fondation Eclipse.

En regardant l’état d’avancement on peut voir que la migration d’une bonne partie des projets est déjà bien avancée.

Un point sur les licences

Le système actuel de licence d’Oracle (CDDL4 et GPL5v2 des spécifications, API et RI ; TLDA6 pour l’usage des TCK et de la marque JavaEE) vont également changer en Eclipse Public License (EPLv2)

Comment la plateforme évoluera-t-elle ?

Les API sortent du giron de JCP7 et des JSR8 pour rejoindre le système des Working Group d’Eclipse et du processus de spécification de la fondation.
Grâce à ce changement, l’Eclipse Foundation espère une plus grande agilité et flexibilité.$
On nous indique que la stratégie d’évolution sera la standardisation a posteriori des bonnes idées qui ont fait leurs preuves à l’instar des exemples célèbres comme Hibernate, Weld, Jersey qui ont donné JPA, CDI et JAX-RS.
Notons que le JCP ne disparaît pas, il continue de fonctionner pour ce qui concerne JavaSE.

JakartaEE vs. MicroProfile

JavaEE 6 a vu l’arrivée de la notion de profil (Web Profile, Full Profile) au sein de la plateforme JavaEE. Le constat de l’époque étant que toutes les applications n’avaient pas besoin de l’ensemble des technologies de la plateforme.
Avec l’arrivée du Cloud Computing et succès des architectures micro-service (comprendre à base de VM), Eclipse MicroProfile propose une spécification de profil encore plus minimal, concurrent direct de Spring Boot [7], basé essentiellement sur les API standard CDI, JAX-RS et JSON-P auxquelles s’ajoutent quelques API nouvelles (Config, Health, Metrics, …).

MicroProfile

Eclipse MicroProfile [8] est donc une spécification alternative d’un ensemble d’API adaptées à la mise en œuvre d’applications architecturées sous forme de micro-service.
D’abord basé sur un nombre très limités d’API, la plateforme évolue comme le montre le tableau [Table:1]

Évolution de Microprofile
API/MicroProfile 1.0 1.1 1.2 1.3 1.4 2.0
CDI 1.2 2.0
JSON-P 1.0 1.1
JAX-RS 2.0 2.1
Config 1.0 1.1 1.2 1.3
Health Check 1.0
Metrics 1.0 1.1
Fault Tolerance 1.0 1.1
JWT Propagation 1.0 1.1
Open Tracing 1.0 1.1
Open API 1.0
Rest Client 1.0 1.1
JSON-B 1.0

Une des forces des spécifications ouvertes, comme pour JEE, est de permettre de fédérer divers éditeurs. Grâce à cela il existe plusieurs implémentations de MicroProfile (voir le tableau ci-dessous).

Implémentations de MicroProfile
Éditeur Implémentation
IBM Open Liberty [9]
RedHat WildFly Swarm [10]
Payara Payara Micro [11]
Apache Tomee [12]
Hammock Hammock [13]
Kumuluz KumuluzEE [14]

Avec les implémentations de MicroProfile, il est possible de déployer une application de plusieurs façons :

  • l’application, les dépendances et le runtime sont packagés dans un seul et même JAR exécutable.Format popularisé par Maven et Spring Boot, la taille de l’archive peut devenir si importante que cela peut poser des problèmes lors de déploiements fréquents (déploiement continu)
  • L’archive JAR contient l’environnement d’exécution, l’archive WAR les ressources métier et les éventuelles dépendances tierces.Avantage, Le WAR est plus léger à déployer car il ne contient que ce qui est spécifique au métier. Cela rappelle le mode de déploiement dans un serveur JavaEE.

12-Factor Application

Pour rappel, «Application à 12 facteurs» est une méthodologie pour construire des applications SAAS9.
Les 12 facteurs en question sont:

  1. Une seule base de code, versionnée (Codebase)
  2. Déclarer explicitement et isoler les dépendances (Dependencies)
  3. Ne pas stocker la configuration dans le code (Config)
  4. Tous les services sont vus comme des ressources «tierces» (Backing services)
  5. Stricte séparation entre la construction, la livraison et l’exécution d’une application (Build, release,run
  6. Les processus d’une application sont sans-étatProcesses
  7. Les services (Web) sont exposés via un port réseau (Port Binding)
  8. L’application se décompose en processus parallèles (Concurrency)
  9. L’application doit pouvoir être démarrée et arrêtée à la demande (Disposability)
  10. Garder les environnements (développement ,recette, production) aussi similaires que possible(Dev/Prod parity)
  11. Les logs sont un flux d’événements indépendant de la manière dont ils sont stockés (Logs)
  12. Les processus d’administration doivent s’exécuter dans le même environnement que l’application (Admin Process)

La présentation d’Emily Jiang [2] nous montre comment l’association de la plateforme MicroProfile et Kubernetes permettent de mettre en œuvre une application selon ces principes.

Codebase
Le code source de l’application est géré par Git (sur GitHub).
Dependencies
La construction et la gestion des dépendances est gérée par Maven.
Config
Les configmaps Kubernetes et l’API Config servent à injecter les propriétés de configuration dans l’application.
Build-Release-Run
Une plateforme d’intégration continue prend en charge le packaging pour chaque environnement.
Processes
L’API REST permet de mettre en œuvre les processus sans-état
Port Binding
Kubernetes et l’API Config sont responsable de l’affection des ports
Concurrency
Le découpage en micro-services et Kubernetes permettent de gérer la mise à l’échelle
Disposable
L’API Fault Tolerance permet de rendre l’application résiliente aux arrêts des processus.
Dev/Prod Parity
Kubernetes Helm permet de s’assurer que les différents environnements sont similaires
Logs
ELK10 permet d’indexer et de gérer les journaux.
Admin Process
L’outillage standard de Kubernetes (kubectl exec) permet des déclencher les processus d’administration.

Sécurité sans-état avec JWT

La sécurité est un aspect fondamental pour les applications d’entreprise, celui-ci est d’ailleurs pris en compte dans JavaEE (avec plus ou moins de souplesse) depuis les tous débuts de la plateforme.
Les architectures micro-service («SOA avec un nom sexy» dit Jean-Louis Monteiro [3]) ne font pas exception, mais l’aspect sans-état nécessaire pour faciliter la gestion de la charge change la donne.
Jean-Louis discute des inconvénients des différentes options d’authentification et de propagation des identités:

Basic Auth
présente plusieurs risques car :
– le couple login/motdepasse est envoyé à chaque requête,
– risque d’attaque DOS du référentiel de sécurité.
OAuth 2.0
basé sur une paire de jetons (access/refresh) recrée au final une session HTTP côté serveur pour garder une trace des jetons générés (et confiés au client) : cela consomme de la mémoire et du temps de calcul car chaque micro-service activé doit vérifier les tokens
JWT
est un format de jeton similaire à SAML mais codé en JSON. Ils contiennent des informations signées et potentiellement chiffrées. Dans ce cas de figure les informations signées, donc non altérables, sont stockées côté client.

L’association JWT + OAuth 2.0 permet de réduire considérablement les ressources nécessaires côté serveur : seules des références de jeton sont conservées (pour la révocation) et chaque service peut vérifier la signature du jeton de manière autonome.
Une présentation de la mise en œuvre de se mécanisme avec l’API JWT propagation de la plateforme MicroProfile vient enfin compléter la brillante démonstration.

JakartaEE + IOT

Une démonstration concrète de la mise en œuvre de technologies JavaEE et de l’Internet des Objets.
Payara Micro [11] est une déclinaison du serveur d’application Payara Server (basé sur Glassfish), pensée pour les micro-services «conteneurisés».
Ce micro-serveur d’application est compatible MicroProfile, mais malgré sa taille (moins de 70Mo),il supporte la mise en cluster, les connecteurs JCA, le Clustering, JCache, les EJB Timer, les événements CDI distribués.
Comment obtenir un serveur d’application si léger ? En faisant l’impasse sur les API historiques les moins pertinentes pour ce genre d’application m’a-t-on indiqué.
Grâce à sa légèreté, sans trop de compromis quant aux fonctionnalités, nous assistons à la démonstration d’une application capable d’agréger des données en provenance de capteurs (d’humidité dans le cas présent) à travers des applications JavaEE déployées sur des nano-ordinateur de type RaspberryPi.
Événements CDI distribués, connecteur JCA pour des échanges de messages asynchrone (MQTT), services REST sont au rendez-vous pour démontrer que les technologies JavaEE ont aussi leur place dans le monde des ressources contraintes de l’IOT.

Kubernetes : retour d’expérience

La fondation Eclipse est en cours de migration de sa plateforme d’intégration continue depuis Cloodbees Jenkins Enterprise vers une solution basée sur un cluster Kubernetes (OpenShift).
À partir de sa propre expérience de migration, Mikaël Barbero nous présente une excellente introduction à Kubernetes [1]
Kubernetes [15] est un système Open Source d’orchestration de conteneurs (VM) permettant d’automatiser le déploiement, la configuration, la gestion et la montée en charge d’applications ou de micro-service «conteneurisés».
Contrairement à la plateforme JavaEE où le conteneur – la machine virtuelle Java – est limitée à l’exécution de bytecode, les conteneurs (machines virtuelles) gérés par Kubernetes sont plus génériques car indépendants d’un OS, d’un langage et d’une plateforme pré-définis.
Là ou les serveurs d’application JavaEE permettaient d’orchestrer des machines virtuelles Java au sein d’un cluster, des outils comme Kubernetes réalisent sensiblement le même travail avec des conteneurs Docker dans le cas présent.
On perçoit comment ont évolués les usages ces dernières années: plutôt que de dépendre des capacités d’un serveur d’application JavaEE, limitées plus ou moins au monde Java, on préfère utiliser un outillage tiers pour gérer un cluster de machines virtuelles plus générales

Conclusion

Que ne lit-on pas ici et là sur la nature «monolithique» de la plateforme JavaEE, que l’on oppose à une architecture fragmentaire des micro-services.
Pourtant JavaEE/JakartaEE ne décrit pas comment doit être implémenté l’environnement d’exécution mais défini seulement un ensemble d’API qui doit être disponible et un format de packaging. Chaque type de composant est d’ores et déjà distribuable, alors pourquoi ne pourrait-on pas voir JEE comme la définition d’une PAAS11 tout à fait capable de construire des applications à base de micro-services ?
Est-ce la difficulté de morceler la plateforme comme ce qui a été réalisé lors des premiers profils (Web et Full) ? Est-ce la nécessité de conserver une compatibilité ascendante ?
Le succès des solutions MicroProfile (ou dans une certaine mesure Springboot ou Dropwizard) nous apprend que:

  • On doit pouvoir choisir les technologies strictement nécessaires à la mise en œuvre d’une application ou d’un composant applicatif.L’intégration de systèmes de modules dynamiques comme OSGI dans les implémentations des serveurs d’applications permet d’ores et déjà de ne charger en mémoire que les composants nécessaires, reste la configuration parfois complexe d’un domaine que l’on voudrait déléguer à des systèmes moins spécifiques.
  • Micro-service ou pas, le contexte des applications d’entreprise nécessite de disposer de solutions pour simplifier la mise en œuvre des aspects transverses (sécurité, transaction, distribution, tolérance aux pannes, métrologie, surveillance, journalisation, …).Il suffit, pour s’en convaincre, de regarder l’évolution des API de MicroProfile. Si les nouvelles API répondent à de nouveaux usages, elles peuvent également profiter à JakartaEE, mais à ce rythme MicroProfile restera-t-il «micro» ?
  • Le choix de la standardisation adoptée par Sun/Oracle ou la fondation Eclipse permet de fédérer les efforts des différents éditeurs et de favoriser la portabilité et l’interopérabilité.

Maintenant que JavaEE est en passe d’être libéré de la tutelle – soit-elle symbolique – d’Oracle, l’enthousiasme des participants à la conférence était au rendez-vous.
Grâce à la disponibilité de systèmes de virtualisation par conteneurs capables d’exécuter des composants (Java ou non); d’outils permettant la gestion d’infrastructures complexes de type Cluster ou Cloud; la modularité sera à mon avis le défi auquel devra répondre la plateforme JakartaEE, soit en intégrant ou définissant de nouveaux profils comme MicroProfile, soit plutôt en proposant une plateforme totalement modularisé pouvant être composée à la carte, à l’instar du travail réalisé sur JavaSE.
Demain, déployer une application JakartaEE consistera-t-il à découvrir à partir d’un paquetage les API utilisées, de provisionner un conteneur contenant le strict nécessaire et d’exécuter le tout ?
Merci enfin à toute l’équipe de la fondation Eclipse qui ont encore une fois réussi à organiser un événement fantastique.
Bravo à tous les conférenciers pour la variété et la qualité des présentations.

Références

1. Mikaël Barbero. 2018. Kubernetes 101. Retrieved from https://www.slideshare.net/mikaelbarbero/kubernetes-101-a-cluster-operating-system/
2. Emily Jiang. 2018. Build a 12-Factor Microservice in Half an Hour. Retrieved from https://www.eclipsecon.org/france2018/sites/default/files/slides/Build12FactorAppUsingMP.pptx
3. Jean-Louis Monteiro. 2018. Stateless Microservice Security via JWT, TomEE and MicroProfile. Retrieved from https://www.eclipsecon.org/france2018/sites/default/files/slides/2018_EclipseConEU_StatelessRESTSecurityWithMP-JWT.pdf
4. 2017. Opening Up Java EE – An Update. Retrieved from https://blogs.oracle.com/theaquarium/opening-up-ee-update
5. Eclipse Enterprise for Java. Retrieved from https://projects.eclipse.org/projects/ee4j
6. JakartaEE. Retrieved from http://microprofile.io/
7. Spring Boot. Retrieved from https://spring.io/projects/spring-boot
8. Eclipse MicroProfile. Retrieved from http://microprofile.io/
9. Open Liberty. Retrieved from https://openliberty.io/
10. WildFly Swarm. Retrieved from http://wildfly-swarm.io/
11. Payara. Retrieved from https://www.payara.fish/
12. Apache TomEE. Retrieved from http://tomee.apache.org/
13. Hammock. Retrieved from https://hammock-project.github.io/
14. KumuluzEE. Retrieved from https://ee.kumuluz.com/
15. Kubernetes. Retrieved from https://kubernetes.io/

  1. DocDoku est membre solution de la fondation Eclipse
  2. Compatibility Test Suite
  3. Tehnology Compatibility Kit
  4. Common Development and Distribution License
  5. Gnu Public License
  6. Technology License and Distribution Agreement
  7. Java Community Process
  8. Java Specification Request
  9. Software As A Service
  10. Elasticsearch, Logstash, Kibana
  11. Platform As A Service

Retrouvez DocDoku sur l’EclipseCon 2018

Les 13 et 14 juin prochains, DocDoku vous donne rendez-vous dans la ville rose pour l’EclipseCon France 2018, le grand rassemblement annuel français de la communauté Eclipse.

Comme lors de la précédente édition, DocDoku reste fidèle à son engagement en tant que sponsor de l’événement et vous accueillera sur son stand pour parler solutions et technologies, mais également présenter ses derniers cas clients.
Le programme de la conférence 2018 couvrira cette année des sujets en lien avec la modélisation, les systèmes embarqués, le Cloud, la Data Analytics, le DevOps et plus encore, le tout agrémenté de sessions de démonstration des outils basés sur Eclipse.

Cette année nous serons particulièrement attentifs aux conférences sur l’arrivée dans la fondation du groupe de travail JakartaEE, auquel DocDoku appartient désormais.
En effet, ce projet ambitieux prend la suite de la renommée plateforme de développement d’applications d’entreprise Java Enterprise Edition, maintenue par Oracle précédemment.

Nous resterons également captivés par les conférences du groupe de travail Polarsys, auquel DocDoku participe également au travers de la plateforme PLM d’Eclipse EPLMP.

13 et 14 juin 2018
Centre de Congrès Pierre Baudis
11 esplanade Compans Caffarelli
31000 Toulouse

Lien direct vers le formulaire d’inscription : ici

Les tests unitaires avec Mockito

Les tests unitaires

Egalement appelés « TU », ils sont destinés à tester une unité du logiciel. Afin d’être vraiment unitaires, ils doivent être en totale isolation pour ne tester qu’une classe et qu’une méthode à la fois.

Tester le bon comportement de son application c’est bien, détecter les éventuelles régressions c’est encore mieux ! Et c’est là que réside tout l’intérêt d’écrire des TU.

De la théorie… à la bonne pratique

Un test unitaire doit être véritablement unitaire. Pour cela, les appels aux services, aux bases de données et fichiers doivent être évités. Le TU doit s’exécuter le plus rapidement possible afin d’avoir un retour quasi immédiat.

Un TU faisant partie intégrante du code applicatif, les pratiques suivantes sont recommandées :

  • il doit respecter les conventions de code
  • il doit être simple et lisible,
  • il ne doit tester qu’un  seul comportement à la fois
  • il doit faire le moins d’appel possible aux dépendances
  • l’utilisation de mocks est recommandée pour fiabiliser les TU.

Un mock est un objet qui permet de simuler un objet réel tel que la base de données, un web service…

L’approche TDD (Test Driven Development) reste la meilleure solution pour éviter que les tests soient écrits à la fin du développement de l’application.

Frameworks de mock

L’écriture d’objets de type mock peut s’avérer longue et fastidieuse, les objets ainsi codés peuvent contenir des bugs comme n’importe quelle portion du code. Des frameworks ont donc été conçus pour rendre la création de ces objets fiable et rapide.

La plupart des frameworks de mock permettent de spécifier le comportement que doit avoir l’objet mocké avec :

  • les méthodes invoquées : paramètres d’appel et valeurs de retour,
  • l’ordre d’invocation de ces méthodes,
  • le nombre d’invocations de ces méthodes.

Les frameworks de mock permettent de créer dynamiquement des objets généralement à partir d’interfaces ou de classes. Ils proposent fréquemment des fonctionnalités très utiles au-delà de la simple simulation d’une valeur de retour comme :

  • la simulation de cas d’erreurs en levant des exceptions,
  • la validation des appels de méthodes,
  • la validation de l’ordre de ces appels,
  • la validation des appels avec un timeout.

Plusieurs frameworks de mock existent en Java, notamment :

  • EasyMock,
  • JMockIt,
  • Mockito,
  • JMock,
  • MockRunner.

Dans ce qui suit, nous allons détailler le framework Mockito.

Mockito

mockito

C’est un framework Java très connu permettant de générer automatiquement des  objets ‘mockés‘. Couplé avec JUnit, il permet de tester le comportement des objets réels associés à un ou des objets ‘mockés’ facilitant ainsi l’écriture des tests unitaires.

Configuration du projet

Pour intégrer Mockito à son projet, il suffit simplement de rajouter la dépendance Maven :

<dependency>

<groupid>org.mockito</groupid>

<artifactid>mockito-all</artifactid>

<version>1.9.5</version>

</dependency>

Deux manières sont possibles pour intégrer Mockito dans les tests Junit :

1- Ajouter l’annotation @RunWith (MockitoJunitRunner.class) à la classe de test :

@RunWith(MockitoJunitRunner.class)

public class MyTestClass {

}

2- Faire appel à la méthode initMocks dans la méthode de SetUp :

@Before

public void setUp() {

MockitoAnnotations.initMocks(this);

}

Création d’objets mockés avec @Mock

La création d’objets mockés se fait soit en appelant la méthode mock(), soit en rajoutant l’annotation @Mock pour les instances de classes.

User user = Mockito.mock(User.class);

ou

@Mock

User user;

Mockito encapsule et contrôle tous les appels effectués sur l’objet User. Ainsi user.getLogin() retournera tout le temps null si on ne « stubb » pas la méthode getLogin().

Définition du comportement des objets mockés ou « Stubbing »

Le stubbing permet de définir le comportement des objets mockés face aux appels de méthodes sur ces objets. Plusieurs méthodes de stubbing sont possibles :

  1. Retour d’une valeur unique

Mockito.when(user.getLogin()).thenReturn(‘user1’); //la chaine de caractères user1 sera renvoyée quand la méthode getLogin() sera appelée.

  1. Faire appel à la méthode d’origine

Mockito.when(user.getLogin()).thenCallRealMethod();

  1. Levée d’exceptions

Mockito.when(user.getLogin()).thenThrow(new RuntimeException());

Il faut noter que la méthode retournera toujours la valeur stubbée, peu importe combien de fois elle est appelée . Si on stubb la même méthode ayant la même signature plusieurs fois, le dernier stubbing sera pris en compte.

Mockito.when(user.getLogin()).ThenThrow(new RuntimeException()).ThenReturn(« foo »);

Ici le premier appel va lever une exception, tous les appels qui suivront retourneront « foo ».

  1. Retours de valeurs consécutives

Mockito.when(user.getLogin()).thenReturn(‘user1’,’user2’,’user3’);

Le premier appel retourne user1, le deuxième retournera user2 le troisième user3. Tous les appels qui suivent retourneront la dernière valeur c’est à dire user3.

  1. Ne rien retourner

 Mockito.doNothing().when(user.getLogin());

Espionner un objet avec @Spy

Au lieu d’utiliser l’annotation @Mock, nous pouvons utiliser l’annotation @Spy. La différence entre les deux réside dans le fait que la deuxième permet d’instancier l’objet mocké, ce qui peut être très utile quand nous souhaitons mocker une classe et non pas une interface.

Une autre différence est à signaler est le stubbing. Si nous ne redéfinissons pas le comportement des méthodes de l’objet espionné, les méthodes réelles seront appelées, alors qu’avec @Mock, nous sommes obligés de spécifier leurs comportements, sinon la valeur nulle est retournée par défaut. Dans l’exemple qui suit la méthode getLogin() sera appelée.

@Spy

User user = new User(‘user1’);

user.getLogin() // retourne user1

Vérification d’interactions @Verify

@Verify permet de vérifier qu’une méthode a été bien appelée et que que les interactions avec le mock sont celles attendues.

Nous pouvons également vérifier le nombre total de fois ou la méthode a été appelée (atMost(3),atLeastOnce(),never(),times(5)) , l’ordre des invocations des objets mockés en utilisant inOrder() et aussi vérifier si une méthode a été invoquée avant la fin d’un timeout. Nous pouvons également ignorer les appels stubbés en utilisant ignoreStubs() et aussi vérifier qu’il n y’a pas eu  d’interaction en utilisant verifyNoMoreInvocations().

verify(user).getLogin();

//le test passes si getLogin() est appelée avant la fin du timeout

verify(mock, timeout(100)).getLogin();

Injection

Mockito permet également d’injecter des resources (classes nécessaires au fonctionnement de l’objet mocké), en utilisant l’annotation @InjectMock. L’injection est faite soit en faisant appel au constructeur, soit en faisant appel au ‘setter’ ou bien en utilisant l’injection de propriétés.

public Class DocumentManagerBeanTest{

@Mock EntityManager em;

@Mock UserManager userManager;

@Spy RoleProvider role = new RoleProvider();

@InjectMocks DocumentManagerBean docBean;

@Before public void initMocks() {

MockitoAnnotations.initMocks(this);

}

@Test

public void uploadDocument(){

docBean.uploadDoc(file);

}

}

public Class DocumentManagerBean {

private EntityManager em;

UserManager user;

RoleProvider role

public String uploadDoc(String file){

if (user.hasAcess()){

em.checkFileExists(file);

….

}

}

}

Conclusion

Mockito est un framework de mock qui, associé à Junit, permet :

  • une écriture rapide de tests unitaires,
  • de se focaliser sur le comportement de la méthode à tester en mockant les connexions aux bases de données, les appels aux web services …

Cependant il a certaines limitations, en effet , il ne permet pas de mocker :

  • les classes finales,
  • les enums,
  • less méthodes final,
  • les méthodes static,
  • les méthodes privées,
  • les méthodes hashCode() et equals().

Aussi, les objets ‘mockés’ doivent être maintenus au fur et à mesure des évolutions du code à tester.

Les micro services peuvent-ils remplacer les serveurs d’applications ?

Un concept en fin de vie ?

Durant ces dix dernières années, particulièrement dans l’écosystème Java, le serveur d’applications fut le roi. Tout bout de code « server side » finissait fatalement déployé sur cet élément hautement important du système d’information. Comme nous l’enseignons nous-mêmes en formation son rôle est de fournir les services techniques aux applications (connexions aux bases de données, gestion du cycle de vie des composants, module d’authentification, supervision des transactions…) déchargeant ainsi les développeurs de l’implémentation de cette tuyauterie ; tâche critique et souvent difficile.

Cette séparation des responsabilités est au cœur de la philosophie Java EE, la spécification de la plateforme distingue en permanence les activités incombant aux développeurs d’applications de celles prises en charge par les administrateurs gérant l’infrastructure ou encore justement les fonctionnalités devant être assurées par le serveur d’applications.

Si on peut comprendre cette logique, pensée pour les environnements complexes des grandes organisations où le SI est géré de manière centralisée, cette approche souffre néanmoins d’une rigidité et d’une lourdeur certaine, chaque application nécessite avant d’être déployée que l’on paramètre son environnement technique sur son conteneur.

Les micro services

Les micro services s’inscrivent dans une démarche opposée : la notion de serveur d’applications (conteneur) gouvernant l’exécution des composants d’application déployés en son sein n’existe plus. Chaque micro service est une application « standalone » tournant dans son propre processus. Ces applications communiquent entre elles au travers de web services de type REST sans l’intermédiation d’un middleware devenu encombrant, à la manière des commandes Unix qui s’agrègent avec un simple pipe. Leur périmètre est généralement réduit, elles font une chose et s’attachent à bien le faire, ainsi on pourra les réécrire si nécessaire complètement en limitant les coûts.

REST a montré qu’il était néfaste de chercher à s’abstraire coûte que coûte du protocole HTTP, les micro services nous enseignent qu’il n’est sans doute pas optimal de chercher à effacer le système d’exploitation comme les serveurs d’applications Java se sont évertués à le faire, en voulant recréer un OS dans l’OS.

Les frameworks

Qui dit nouveaux paradigmes dit nouveaux frameworks. Toujours dans l’univers Java, il y a bien sûr le presque déjà vieux Playframework qui adopte une stratégie résolument de rupture en proposant une pile logicielle avant-gardiste et encourageant fortement l’usage du langage Scala, même si Java est également supporté. Un autre framework, bien que moins audacieux, mérite tout autant que l’on s’y intéresse, il s’agit de Dropwizard. Ce framework possède l’avantage de capitaliser sur des technologies matures, bien connues des développeurs Java EE comme Jersey, Jackson, Jetty ou encore Hibernate validator. La courbe d’apprentissage sera donc douce.

Allez bonne année et RDV en 2013 pour mettre tout ceci en pratique !

Retour sur DevoxxFR

Jeudi 19 et vendredi 20 avril avait lieu à Paris la conférence DevoxxFR,  par et pour les développeurs java.

La première chose à souligner est l’immense succès de cette première grande conférence puisque nous étions 1250 personnes réunies à l’hôtel Mariott pour les deux derniers jours.

À l’occasion de la sortie des vidéos sur la plateforme Parleys, petit retour sur quelques conférences que j’ai eu l’occasion de voir.

Keynotes

Les deux keynotes qui m’ont particulièrement marquées sont celles de Neal Ford et de Patrick Chanezon.

Dans Abstraction Distractions, Neil Ford nous parle de l’empilement des couches d’abstractions qui envahissent notre quotidien sans qu’on y prête plus vraiment attention et qui peuvent parfois nous induire en erreur. Il nous conseille de toujours avoir à l’esprit ce qui se passe en dessous de la couche que l’on utilise.  Sa keynote est agrémentée d’anecdotes qui font sourire l’auditoire.  Du gros niveau !

Patrick Chanezon enchaîne ensuite avec le portrait d’un développeur en reprenant la trame de The Artist.  On suit le parcours d’un mec qui pendant plusieurs années est le roi du pétrole à coder du cobol dans des SI bien complexes dont seul lui a le secret (=période où Jean Dujardin est une star du cinéma muet).  Puis à l’arrivée de nouvelles technos sympa type mobile, cloud, html5 (=l’arrivée du cinémas parlant) le dev ne s’y intéresse pas et reste dans sa zone de confort.  Malheureusement pour lui ces nouvelles technos prennent de plus en plus de place et notre ami se retrouve rapidement dépassé et remisé au placard (=dépression de Jean Dujardin).

Mais finalement tout est bien qui finit bien car notre développeur se prend en main, réalise qu’il fait partie d’une communauté de passionnés, participe à des jugs et vient à Devoxx. Et finalement cela donne une keynote plutôt rafraîchissante et pleine d’humour.  Bien joué.

Play Framework 2.0

Un mois après la release de la version 2, Sadek Drobi, CTO de Zenexity et Guillaume Bort, cofondateur de Zenexity et créateur de Play Framework retracent l’histoire du web pour expliquer les fondements du framework.

Au départ, le web était constitué de pages statiques puis nous sommes passés dans une phase de langages dynamiques avec notamment PHP, il a fallu ensuite structurer tout ça et c’est à cette époque que sont apparus les premiers frameworks MVC. Plus proche de nous, on a assisté à la démocratisation d’Ajax qui nous a apporté la mise à jour des pages sans besoin de recharger le navigateur.

Aujourd’hui, une page est bien souvent constituée de fragments autonomes, « bindés » sur des flux de données.  Sadek et Guillaume prennent l’exemple de twitter.  Le besoin est réel de structurer ces flux car nous sommes en plein dans l’ère du web temps réel.

C’est sur ce constat qu’a été bâti Play Framework 2,  apporter un socle pour structurer l’interaction avec des streams de manière efficace.

Et voilà du coup ce qu’il est possible de faire : http://console-demo.typesafe.com l’explication ici : http://typesafe.com/products/console

La présentation continue avec comme leitmotiv « don’t fight the web » :  il ne sert à rien d’abstraire le web mais au contraire il faut bâtir en s’appuyant dessus.  Ce que l’on retiendra c’est que Play Framework est un framework stateless full stack qui embrasse le protocole http.

D’un point de vue personnel, cette présentation m’a donné envie d’explorer plus en détail la version 2 de Play, la version 1 apportait déjà beaucoup de fun dans les développements.  Chez DocDoku, nous l’utilisons d’ailleurs en production sur certains projets.

Behind the Scenes of Day-To-Day Software Development at Google

Petra Cross de Google vient nous parler des méthodes de développement chez Google, elle nous présente d’abord la hiérarchie type d’une équipe de développement puis nous parle des méthodes de travail.  On apprend que les maîtres mots sont ‘pragmatisme’ et ‘efficacité’. Par exemple l’équipe de Petra applique l’agilité dans le sens où ils utilisent un backlog de tâches, par contre ils ont totalement supprimé le standup meeting qui selon elle est une perte de temps  (j’entends les agilistes hurler !).

Un concept intéressant massivement utilisé chez Google est le ‘eating your own food’,  il s’agit d’utiliser soit même les produits que l’on conçoit. Ainsi  les googlers utilisent en interne les nighlty build de leurs produits ce qui permet d’avoir un feedback très rapide et de qualité sur les développements.

Conférences Android

J’ai eu l’occasion d’assister à deux conférences sur Android :  « Optimiser vos applications HTML pour Android » et « Android, Graphisme et Performance ». La première présentée par Romain Guy était un condensé de trucs et astuces afin d’optimiser l’IHM des applications Android.

Parmi les astuces et optimisations vues :

  • ViewStub : permet d’instancier (« inflater ») des vues au runtime uniquement si besoin. Cela limite l’empreinte mémoire des View qui peut être très coûteuse, par exemple une TextView vide prend 800 octets en mémoire.
  • StrictMode : outil de debug qui permet d’être notifié lorsqu’une opération lente est effectuée (écriture et lecture disque, opération réseau) ou lorsque une fuite mémoire est détectée (fuite sur les objets sqlite, objet closable non fermé, fuite des activity)
  • GridLayout : nouveau layout introduit d’ICS, moins gourmand que LinearLayout.  Pour les versions Android précédentes, Romain nous conseille RelativeLayout là où c’est possible plutôt que LinearLayout
  •  hierarchyviewer : outil du sdk qui permet de visualiser les grappes de vues et d’analyser leurs performances.

Romain nous détaille également une spécificité des AsyncTask : à partir de l’API level 12 les AsyncTask sont exécutées de manières sérialisées, les unes après les autres. Attention donc à ne pas ralentir la file d’exécution avec une tâche trop longue. Google justifie ce changement en expliquant que la programmation multithread est compliquée. Ils ont donc décidé de revenir sur le comportement par défaut pour limiter les bugs potentiels. Par contre si l’on est sûr que les tâches sont totalement thread-safe, il est tout a fait possible programmatiquement de revenir au comportement précédent.  Ainsi pour paralléliser les AsyncTask il suffit d’appeler :

task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

La deuxième conférence Android est celle du googler Nicolas Roard qui travaille sur la webview Android. Nicolas nous délivre quelques astuces pour optimiser les performances dans une webview.  Il nous recommande de privilégier le CSS3 plutôt que le javascript lorsque l’on souhaite faire une animation.

Il nous explique également comment forcer la création de layers qui seront accélérés de façon hardware à partir de la version 3.  Pour cela il suffit d’appliquer une propriété css de transform 3D sur un élément.  On peut également créer un layer sur un scroll afin d’obtenir un rendu proche du natif grâce à la propriété css overflow scroll.

Attention tout de même, ces layers ont certes un rendu fluide mais ils sont très couteux. Il est donc conseillé de les utiliser avec parcimonie, par exemple uniquement durant une animation.

Nicolas termine par 25 minutes de questions/réponses. Les questions majoritairement posées tournent autour des performances de la webview qui souffre de la comparaison avec l’application Google Chrome pour Android.

Il nous explique que même si les deux s’appuient sur le moteur de rendu webkit, les contraintes ne sont pas les mêmes. La webview fait partie intégrante du framework, l’équipe a donc des contraintes quant à la mémoire et l’espace disque utilisé, la webview doit être compatible avec un maximum de choses et rétro compatible avec les précédentes releases. L’équipe de Nicolas a notamment fourni un effort de travail spécifique pour afficher correctement les widgets jquery mobile.

Toutes ces contraintes ne sont pas applicables à Chrome, Chrome est téléchargé depuis le market, c’est un choix de l’utilisateur, par conséquent ils ont beaucoup plus de liberté. Ils peuvent prendre des décisions, avancer vite et releaser souvent, chose impossible à faire pour la webview qui doit attendre une nouvelle version d’Android pour être mise à jour.

Nicolas conclut en nous assurant que les deux équipes mettent en commun beaucoup de travail et que tout le monde en tire un bénéfice.

Quickies

Entre midi et deux avaient lieu les quickies, un format court de conférences où en 15 minutes un speaker présente un sujet qui lui tient à cœur.

J’ai pu notamment voir Mathilde Lemee nous présenter son projet FluentLenium qui facilite l’écriture des tests Selenium en proposant une API très lisible (d’où le fluent !). Et effectivement quand on regarde l’exemple de base, on comprend tout de suite le test :

public class BingTest extends FluentTest {
    @Test
    public void title_of_bing_should_contain_search_query_name() {
        goTo("http://www.bing.com");
        fill("#sb_form_q").with("FluentLenium");
        submit("#sb_form_go");
        assertThat(title()).contains("FluentLenium");
    }
}

FluentLenium s’appuie sur les selectors CSS (même si les regex sont possibles). Enfin la dernière chose à noter sur le projet est qu’il est agnostique du framework d’assertion, ainsi jUnit Assert, Hamcrest et Fest-assert sont supportés.

Un deuxième quickie assez fun fut celui de Philippe Antoine qui s’est proposé de recoder en live le tetris de Martin Kleppe dont une version est jouable ici : http://jsbin.com/egiqul/49

La spécificité initiale de ce Tétris est d’être codé en 140 caractères, cette performance est possible en utilisant le décalage binaire.

Philippe se lance donc dans la réalisation du Tétris avec l’aide de la salle,  il en profite pour nous montrer comment faire du TDD en javascript avec QUnit. Un quickie original qui a bien plu.

Code Story

Pendant les deux jours de conférences, une équipe de quatre développeurs a codé en live une application from scratch. Chaque slot de conférence a donné lieu à un sprint. Ils ont fonctionné en pair programming avec un binôme codant pour la salle : ordinateur relié au vidéo projecteur en commentant le code.  J’ai eu l’occasion d’assister à un sprint, et par la même occasion j’ai pu découvrir Trello un super outil très souple et très simple de gestion de projet.

Conclusion

En tant que développeur, je me suis régalé durant ce Devoxx, j’ai pu satisfaire ma curiosité sur des sujets totalement nouveaux pour moi, comme me plonger dans des astuces plus techniques sur des sujets comme Android.  Si je devais dégager des keywords de cette grande et belle conférence, je choisirais :  cloud, mobile, html5 & javascript, NoSQL.

GWT est-il toujours pertinent ?

Il y a 3 ans, lorsqu’il s’agissait de définir le socle technique d’une nouvelle application web, en l’absence de contraintes exogènes, GWT (Google Web Toolkit) était pour nous un choix naturel pour le développement de la partie « front web ». Les arguments massue de l’époque étaient le manque de portabilité de JavaScript, son faible niveau d’outillage par rapport à Java et aussi la grande difficulté que l’on peut rencontrer à développer une large application avec un langage aussi dynamique et faiblement typé que JavaScript. Face à ces écueils, GWT représentait le rempart absolu, la solution ultime.

Aujourd’hui toutefois, les choses ont de mon point de vue quelque peu évolué.
Tout d’abord, le support de navigateurs obsolètes, comme Internet Explorer 6 par exemple, n’est plus l’obsession des DSI qui par contre tiennent de plus en plus à ce que leurs applications offrent également un bon rendu sur les dispositifs mobiles et tactiles.

Ensuite, l’écosystème JavaScript a progressé. Si les jQuery et autres Prototype existaient déjà il y a 3-4 ans, des frameworks de plus haut niveau tels que Backbone.js, JavaScriptMVC, s’appuyant d’ailleurs sur jQuery, ont fait leur apparition. Ceux-ci aident à fournir un cadre à la structuration des applications de grandes tailles, point délicat lorsque le volume de JavaScript devient important. Des moteurs de templates côté client comme mustache ou des starter kits, à l’instar de bootstrap twitter, sont également venus enrichir l’offre JavaScript.

Côté GWT aussi les lignes ont bougé, passés les premiers instants d’émerveillement, quelques défauts se sont fait sentir. Le premier d’entre eux est l’absence d’une vraie bibliothèque de widgets solide et pérenne. GWT étant avant tout un socle technique, Google laisse à la communauté ou aux éditeurs tiers le soin de bâtir sur son framework. Ainsi Ex GWT, SmartGWT, Vaadin pour ne citer qu’eux disposent de composants de plus haut niveau, prêt à l’emploi. Malheureusement ces bibliothèques n’ont jamais donné pleinement satisfaction : licence peu « business friendly », adhérence importante, problème de qualité. Au final, la sagesse recommande de se contenter de GWT et de tout développer soi-même…
Par ailleurs, GWT, au fil des versions, a gagné en complexité, le pattern « activities/places » pour être correctement employé exige que les développeurs soient bien formés ; RequestFactory, CellWidget sont des nouveautés qu’il conviendra à nouveau d’assimiler et qui contraindront la migration d’un bon nombre d’applications.
En outre, si GWT parvient à éloigner complètement JavaScript du développeur, il ne le préserve pas de CSS qui tend à prendre de plus en plus d’importance et devient une nouvelle source d’incompatibilité entre les navigateurs. On touche finalement au coeur du problème : GWT est une abstraction imparfaite ; cette encapsulation des technologies web ne dispense pas les développeurs d’en comprendre les arcanes.

Conclusion
Pour répondre très concrètement à la question posée par ce billet : oui GWT est toujours pertinent surtout s’il s’agit d’implémenter une grosse application de gestion avec des développeurs de niveau hétérogène. Par contre, pour une application innovante, faisant un usage prononcé des dernières fonctionnalités HTML5 (3D, communication temps réel) il est avantageux d’être en prise directe avec le browser (bare metal).
Quoi qu’il en soit, ce qui était annoncé à la sortie du framework de Google ne s’est pas produit : JavaScript n’est pas devenu l’assembleur du web. Qu’on le déplore ou non, ce langage est aujourd’hui incontournable, son champ d’application dépasse d’ailleurs largement le cadre du navigateur (CommonJS). Aucun développeur IT ne peut continuer à le bouder.

DocDoku et Webinage font carton plein à la Mêlée Numérique XV !

Cette année encore, DocDoku était présent à la Mêlée Numérique et accompagné d’un partenaire de grande qualité avec Webinage.

Sur le stand de DocDoku, vous avez pu assisté à la présentation de l’application tactile que nous avons réalisée pour et avec Webinage.

Vous avez été également très nombreux à vouloir une démonstration de notre solution de GED Open Source disponible en SaaS.

Ces deux journées ont donc été plus que satisfaisantes pour l’équipe DocDoku car un public de qualité était au rendez-vous.

La conférence sur « HTML 5 ou l’évolution majeure du web et de l’internet mobile » présentée par Florent Garin notre Directeur Technique et Thomas van de Velde, Directeur Général de Webinage a rencontré un grand succès, avec la participation d’une centaine de personnes dans la salle !

Si vous n’avez pas pu assisté à la conférence, la présentation sera prochainement disponible sur notre blog et sur le site internet de la Mêlée Numérique.

Hibernate dirty checking

Les ORM (Object-Relational Mapping) sont aujourd’hui des technologies matures ; l’essentiel d’Hibernate a été versé au standard Java EE au travers de la spécification JPA qui en est maintenant à sa deuxième version.
Les réfractaires à la technologie, qui préfèrent encore utiliser directement l’API JDBC ou (moindre mal) les templates JDBC de Spring, sont aujourd’hui de moins en moins nombreux. Malgré tout, s’il est donc vrai qu’un ORM apporte une solution élégante à la problématique de persistance de nos applications, il faut aussi admettre qu’en déléguant une partie du travail d’interaction avec la base de données à ces outils nous perdons un peu en contrôle ce qui introduit de nouvelles difficultés. Parmi celles-ci il y a la bonne prise en compte du « dirty checking ».

Le « dirty checking » est un mécanisme d’Hibernate qui consiste à lister parmi les objets attachés ceux qui ont été modifiés pour ensuite propager ces modifications en base. Ce comportement du framework doit être bien compris car il peut être source d’effets secondaires indésirables.

Hibernate peut lancer une opération de « dirty checking » à plusieurs occasions :

  • Lors d’un flush, qui intervient au moment du commit de la transaction ou d’un appel explicite par EntityManager.flush(),
  • Juste avant l’exécution d’une requête de type « select ». Ce cas de figure peut sembler moins évident que le premier mais la raison est relativement simple : la requête sera exécutée au niveau de la base de données, il est par conséquent capital que les données modifiées dans la transaction en cours qui peuvent influencer le résultat de la requête soient « flushées ».

Si la plupart du temps, le « dirty checking » se fait dans la plus grande transparence sans que le développeur n’ait à s’en soucier, il arrive aussi que son déclenchement soit gênant. Par exemple dans le cas de traitement de masse où le nombre d’objets attachés est très important cette opération peut pénaliser fortement les performances. Par ailleurs, si l’on souhaite avoir la main sur l’ordonnancement des requêtes SQL, il est embêtant qu’une simple recherche JPQL déclenche une série de requêtes de type « update » à la suite d’un « dirty checking ».

Comment faire alors pour maîtriser la propagation des modifications dans la base et éviter les traitements de « dirty checking » intempestifs ?

Hibernate étant un framework souple et paramétrable, il offre pas mal de possibilités au développeur pour gérer cela : on peut travailler dans un mode « read only », on peut aussi utiliser la classe StatelessSession qui est spécialement pensée pour dérouler des opérations en bloc (sans « dirty checking » automatique). Si l’on préfère, probablement à raison, rester sur le standard JPA, il suffit de positionner le « flush mode » comme ceci :

EntityManager.setFlushMode(FlushModeType.COMMIT);

Ainsi les objets ne seront synchronisés avec la base de données qu’à la fin de la transaction, au moment du commit. Évidemment, il faut là aussi être sûr de son coup, il convient de bien vérifier qu’aucune requête de sélection ne sera perturbée par ce flush tardif.

JSF 2.0, enfin correct !

Voila quelques mois maintenant sortait dans sa version finalisée la spécification Java EE 6.
Dans la foulée la version 3 de glassfish était mise à disposition.

Globalement, la plateforme va vers plus de modularité et de simplicité avec notamment la généralisation des annotations ou encore l’apparition des profils qui servent à regrouper les API Java EE en plusieurs familles. Pour l’instant, il n’existe que deux profils, le profil complet et le profil Web.

Java EE a clairement atteint aujourd’hui l’âge de la maturité, le modèle de développement standard Java pour les applications d’entreprises n’a plus de véritables faiblesses comme par le passé avec les abominables EJB2. Malgré tout, parmi les nombreuses briques définies par la spécification, il en reste une que les développeurs auront tendance à substituer par une alternative open source ; je pense à JSF.

JSF n’a jamais été le framework brillant devant lequel on tombe en émerveillement le jour où on le découvre. Il n’a pas l’étoffe d’un Struts qui au début des années 2000 structura en MVC nos applications web ni la souplesse de Spring Ioc, la puissance de Spring AOP ou encore la simplicité de GWT. Toutefois la version 2 efface les principaux reproches qui étaient faits au framework en apportant :

  • Support de la méthode HTTP GET qui permet de faire des URLs « bookmarkable »
  • Support d’AJAX avec le rendu partiel de la vue
  • Moteur de templating
  • Navigation implicite entre les pages (<navigation-rules> n’est plus obligatoire)
  • Facelets préféré aux JSP

Ainsi aujourd’hui, il est possible de choisir JSF 2 pour implémenter la couche de présentation d’une application web sans forcément faire une erreur !

Portail Liferay avec GWT intégré en SOA pour Pierre et Vacances

Aujourd’hui je viens vous faire partager une très belle expérience projet. Je vous parlerai donc d’un projet que nous avons réalisé pour notre client Pierre et Vacances, qui a su nous faire confiance jusqu’au bout pour le développement et l’infogérance de son extranet commercial.

Faire des choix en matière d’architecture logiciel en 2010 peut être un exercice difficile, c’est pourquoi l’approche de DocDoku en matière de choix techniques est basée sur les principes suivants :

  • pragmatisme, dans le choix des langages et des technologies,
  • ouverture d’esprit, nous effectuons une veille technologique permanente,
  • mise en contexte, chaque problème étant différent, les réponses à apporter doivent l’être également,
  • industrialisation, il ne s’agit pas de s’emparer de la toute dernière nouveauté mais de bâtir des solutions robustes, matures et maintenables,
  • respect des standards établis, pour garantir la pérennité des applications, et maximiser l’investissement consenti par nos clients, nous nous appuyons sur les standards unanimement reconnus.

Dans le cadre de l’extranet commercial développé pour Pierre et Vacances, les grands principes architecturaux retenus ont été les suivants :

  • utilisation du composant portail open source Liferay permettant un gain de productivité certain en particulier sur les modules génériques (droits d’accès, profils utilisateurs, agenda, publication de news…) mais respectant également la JSR 286, norme de communication entre le portail et les applications qui y sont hébergées, supportée par de nombreux éditeurs (IBM, Sun, Oracle, RedHat). Ceci permet de surcroît de limiter notre dépendance vis-à-vis d’une solution portail en particulier.
  • développement d’une architecture en couches permettant notamment de découpler les composants les uns des autres et de les faire évoluer indépendamment.  Une séparation en couches permet d’adapter en effet l’architecture physique en fonction des besoins de distribution pour une bonne capacité à monter en charge.  Une architecture n-Tiers en 4 couches distinctes a été choisie :
    • La couche d’accès aux données avec JPA-Hibernate dont le rôle est la connexion à la base de données, l’exécution des requêtes ou l’appel des procédures stockées.
    • La couche de service EJB3 et JAX-WS-Metro, ensemble des règles métiers et processus de l’application. Cette couche sera implémentée en Java via des composants transactionnels.
    • La couche métier POJO qui constitue le diagramme de classes des entités (le modèle objet).
    • La couche de présentation avec GWT et Portlet Liferay : l’interface utilisateur affiche les résultats traités par la couche métier.  Ici le framework Ajax GWT a été choisi pour à la fois offrir une ergonomie poussée et une forte maintenabilité.
  • mise en place d’une architecture de type SOA pour pouvoir exposer de façon universelle les fonctions de l’extranet pour les futures applications du SI.

Tout ceci est en production évidemment depuis la fin octobre 2009.

Agilement.

La référence sur GWT 2

J’ai eu le plaisir il y a quelques jours de recevoir, de la main même de l’auteur à l’occasion d’un déjeuner, le livre Programmation GWT 2.

J’ai préféré attendre d’avoir bien parcouru le livre avant d’écrire ce billet. J’aime autant le dire tout de suite : ce livre est LA référence sur GWT 2. Tout y est : les incontournables services RPC, l’intégration JEE, l’UiBinder, la communication avec le monde JavaScript mais aussi les Designs Patterns MVC (Model View Controller) ou MVP (Model View Presenter).

Au niveau de l’approche, la grande force du livre de Sami Jaber est qu’il est didactique et pointu à la fois, il convient donc aussi bien aux débutants qui veulent plonger dans le monde AJAX avec GWT qu’aux développeurs chevronnés. Un signe qui ne trompe pas sur la qualité de l’ouvrage : nos consultants qui ont près de 2 ans d’expériences sur GWT se l’arrachent !

Le cache d’entités JPA

Si le recours à un ORM (Object-Relational Mapping) permet des gains de productivité et facilite la maintenance des applications, ce type de framework introduit néanmoins des problématiques nouvelles, qui, pour être évitées, exigent une très bonne connaissance des mécanismes internes au moteur de mapping.

Parmi ces difficultés classiques, on peut citer la gestion du cache d’objets.

La validation finale de la spécification de JEE 1.6 (JSR 316) qui inclut la version 2 de JPA, intégrant des évolutions appréciables en matière de prise en compte du cache, est l’occasion de revenir ici un peu sur le sujet.

En réalité les ORM possèdent deux caches distincts :

jpa_caches

Cache de premier niveau (L1)

Le cache de premier niveau est rattaché à l’objet EntityManager, il s’agit en fait du « persistence context » qui lui est associé. Pour rappel, c’est à partir d’une instance d’EntityManager que les entités (les objets persistés en base de données) sont créés, récupérés ou encore supprimés. La classe EntityManager est définie par l’API standard JPA, elle est l’équivalente de la classe Session dans l’API native Hibernate.

Le contexte de persistance regroupe un ensemble d’entités en garantissant que pour une même entité il n’y aura qu’une seule instance d’objet. En prenant garde à ne pas dupliquer les objets de même identité, le contexte de persistance agit donc comme un cache d’objets : les recherches, qu’elles soient faites au travers d’une Query ou avec la méthode find(Class<T> entityClass, Object primaryKey), retourneront toujours les mêmes instances d’objets, piochées dans le cache, pour matérialiser un même enregistrement en base. Le contexte de persistance est lié à la transaction en cours, il sera vidé à la conclusion de celle-ci.

Le fonctionnement du contexte de persistance qui vient d’être décrit est celui qui est le plus couramment employé, il s’agit du mode PersistenceContextType.TRANSACTION. Néanmoins, il existe un autre mode dit « étendu », le paramétrage du contexte de persistance se fait dans le code Java, lors de l’injection de l’EntityManager :

@PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;

Dans cette configuration, le PersistenceContext n’aura pas une durée de vie corrélée à la transaction mais au Stateful Session Bean dans lequel il est déclaré. Ainsi, le cache d’objets sera maintenu sur plusieurs transactions à la base de données. Ce type de contexte de persistance peut par exemple être utilisé pour alimenter en données une page web requêtant en AJAX.

Cache de deuxième niveau (L2)

En dessous de ce cache placé sous la direction des EntityManagers se trouve un autre cache dit de second niveau. Ce cache est global à la JVM ou plus exactement à l’EntityManagerFactory. Il peut aussi être configuré au niveau cluster, dans ce cas le cache sera répliqué sur chaque JVM. Le cache de second niveau est donc partagé entre les EntityManagers qui iront l’interroger, si l’entité recherché n’est pas présent dans leur propre contexte de persistance, avant de se résigner à taper dans la base de données.

Si les règles régissant le cache de premier niveau sont relativement limpides, celles gouvernant le cache de 2ème niveau le sont un peu moins et le développeur peut légitimement se poser de nombreuses questions :

  • Quelle est la durée de rétention des objets dans le cache ?
  • Que se passe t-il si la base de données est modifiée en dehors de l’application JPA ?
  • Peut-on contrôler par configuration ou par du code ce cache ?

De manière générale, les réponses à ces questions dépendent avant tout de l’implémentation JPA choisie. D’ailleurs, si EclipseLink et TopLink activent par défaut un cache de second niveau ce n’est pas le cas d’Hibernate. Ce dernier a par contre été très tôt pensé de façon modulaire et accepte divers « cache provider » comme EhCache, OS Cache ou encore JBoss Cache. Chaque système de cache vient avec ses options et ses fichiers de paramétrages, il est souvent possible de les spécifier dans le fichier persistence.xml entre la balise <properties> ou dans le code par la méthode Query.setHint(String hintName, Object value).

En ce qui concerne les changements opérés dans la base sans passer par les couches de persistance de l’ORM ; là le résultat est identique quelque soit le framework : le cache de niveau 2 se retrouve obsolète et cela tant que l’entité en question ne sera pas rechargé. La plupart des caches d’objets utilisant des SoftReferences ou des WeakReferences, l’éviction de l’objet se produira à un moment indéterminé, au gré des pérégrinations du garbage collector. Pour ceux ne pouvant se contenter du caractère aléatoire des références faibles et qui veulent expressément déclencher le rafraichissement des données la classe EntityManager propose heureusement la méthode refresh qui s’utilise habituellement ainsi :

MonEntity e = em.find(MonEntity.class, id);
try {
em.refresh(e);
} catch(EntityNotFoundException ex){
e = null;
}

Toutefois, ce n’est que depuis la version 2 de JPA que le cache L2 est officiellement mentionné dans la spécification. Dans cette API, une classe Cache accompagnée de ses méthodes « evict » a fait son apparition et certains points de configuration ont été standardisés.

En conclusion

Il y aurait encore beaucoup à dire sur les caches d’entités et plusieurs billets seraient nécessaires, c’est pourquoi je conclurai simplement en invitant tous les développeurs et architectes à regarder sous le capon de leur framework de persistance et à ne pas se laisser « endormir » par la simplicité trompeuse de l’API JPA.

Installation de Glassfish sous linux

Comment installer glassfish en tant que service sous linux ?
Contrairement à Windows, installer n’importe quelle application sous forme de service n’est pas très compliqué sous un OS de type Unix.
Le billet suivant explique clairement la démarche à adopter.

Malheureusement, un petit hic survient quand on souhaite faire tourner glassfish sur le port 80.
Sous linux, il est purement et simplement impossible de configurer glassfish sur le port 80 si celui-ci ne tourne pas avec le compte root ce qui est toujours regrettable pour des raisons évidentes de sécurité.

Confronté à ce problème, j’ai tout d’abord envisagé (comme à la grande époque de Tomcat) de positionner un apache écoutant sur le port 80 devant glassfish qui serait lui sur le 8080. Je me suis aussi dit qu’au passage grâce à apache je pourrais faire du « Virtual Hosting » et utiliser les quelques applications php dont nous avons besoin.

Cependant, un tour sur internet, a vite calmé mes ardeurs. Les nombreux commentaires de ce post n’encouragent pas à la confiance.

Finalement, après mûre réflexion, j’ai choisi de laisser glassfish s’exécuter avec le compte root. Hormis cet inconvénient qui je l’espère ne tardera pas à être corrigé, les fonctionnalités natives de « Virtual Hosting » de glassfish, l’architecture modulaire OSGi de la version 3 et le repositionnement de la JVM comme une plateforme multi-langage me font penser que glassfish pourrait bien également concurrencer apache !

JavaOne

JavaOne s’est déroulé au début du mois à San Francisco. Cette conférence a mis à l’honneur Glassfish, le serveur d’application JavaEE Open Source de Sun, avec le lancement du GlassFish Technology Partner Program dont nous faisons partie. Ce partenariat matérialise notre expertise de la plateforme Java en général et de Glassfish en particulier.
L’autre technologie majeure présentée à JavaOne fut JavaFX. Beaucoup pensent que JavaFX arrive trop tard et qu’il ne pourra pas trouver sa place face à des concurrents comme Flash notamment. Pour ma part, je suis convaincu du contraire.
Le succès de Flash est éclatant et cela est largement justifié : très grande facilité de déploiement, temps de démarrage à froid impressionnant, qualité des outils de production, des codecs vidéo…
Néanmoins, dans le cadre du développement d’une application d’entreprise disposer d’un langage aussi riche que Java sur le client, surtout s’il est aussi utilisé sur le serveur, est un énorme avantage. Si JavaFX continue de progresser et que la version finale de Java SE 6 Update 10 tient toutes ses promesses, je recommanderai JavaFX et non Flex à nos clients industriels.

Le futur de JSF

JSF ne s’est pas encore, gardons espoir, véritablement imposé comme LE framework web java.
La première des raisons est sans doute sa complexité. Essayez d’expliquer à un féru de php son Unified Expression Language pour vous en convaincre.
Deuxièmement, la spécification de JSF ne définit qu’une palette de composants graphiques très limité. Dans un projet réel, ceux-ci suffisent rarement ; il faut alors se tourner vers des extensions propriétaires, perdant du même coup la neutralité vis à vis de l’implémentation de JSF.
Enfin, le dernier point problématique est la difficulté d’intégration de JSF et d’AJAX.
Il est en effet compliqué de mixer l’approche purement « server-side » de JSF avec une logique AJAX où une partie du MVC est directement implémentée sur le client en javascript.
La jsr 314, celle de JSF 2.0, devrait remédier à cela en apportant des modifications importantes au cycle de vie notamment le parcours partiel de l’arbre des widgets.
Cela va dans le bon sens, néanmoins, il n’en demeurera pas moins que de plus en plus la logique cliente se trouvera portée par du code AJAX, laissant à JSF la gestion des tâches annexes.
Si JSF 2 marquera indéniablement l’acceptation d’AJAX par Java EE, ne faudrait-il cependant pas aller plus loin, en d’autre terme ; pour préserver sa pertinence, JSF 3 ne devra t-il pas être un framework en bonne partie javascript ?