Thématiques principales

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

mercredi 27 février 2019

OSGI : Karaf ServiceMix

On est presque à la fin du mois et je n’ai écrit qu’un seul article! Heureusement j’ai un sujet au chaud pour combler le vide.

On avait parlé du framework OSGI Felix [osgi-felix] la dernière fois et nous avions vu dans un précédent article qu’il en existe d’autres packages sous la forme de serveur d’application (comme le serait un Jboss [jboss] ou un Weblogic [weblogic]).

Nous allons justement nous intéresser à deux de ses serveurs:
  • Karaf [karaf]
  • ServiceMix [servicemix]

Bien sur ceux les connaissant diront que c’est grosso merdo la même chose, et effectivement, ServiceMix s’appuie sur Karaf mais en apportant un ensemble de bundle dédié à la communication et aux services, c’est à dire les WebServices et les services de messageries (SMTP, JMS, etc…). Il était donc important de le connaître également.

dimanche 3 février 2019

OSGI : Felix

Nous revoilà avec OSGI mais cette fois ci pour aller dans le concret, plus de blabla, maintenant on fait chauffer la JVM.

Le problème du choix

Bien tout d’abord il nous faut choisir un framework, c’est à dire une implémentation. Nous en avons vu plusieurs dans l’article précédent [osgi-fwk] et il nous faudra faire un choix. À mon sens il y avait plusieurs possibilité:

  • Knoplerfish [knoplerfish] est trop compliqué bien qu’à jour dans l'implémentation des versions OSGI
  • Karaf [karaf] est un peu trop lourd pour ce que nous voulons montrer ici (mais nous ferons un article dessus)
  • Equinox [equinox] est sympas je l’aurais choisi si je ne prévoyais pas de présenter mon framework equinox-loader [eq-loader] qui l’utilise
  • Concierge [concierge] est hors propos, on ne va pas faire de Iot
  • Donc en toute logique, on va essayer l’utilisation de OSGI avec Felix [felix]

Tout d’abord il faut télécharger la version courante: c’est ici [felix-down]

Dockerisation

Pour simplifier son utilisation, nous allons préalablement le dockeriser pour faciliter son exploitation, on construit donc un fichier Dockerfile dans un répertoire (moi je l’ai nommé felix-framework) contenant le processus de construction suivant:

FROM openjdk:8-jre-alpine

RUN wget http://mirror.ibcp.fr/pub/apache//felix/org.apache.felix.main.distribution-6.0.1.tar.gz \
&& tar zxvpf org.apache.felix.main.distribution-6.0.1.tar.gz && rm org.apache.felix.main.distribution-6.0.1.tar.gz

COPY . /felix-framework-6.0.1/
CMD cd /felix-framework-6.0.1; java -jar bin/felix.jar


mercredi 30 janvier 2019

OSGI : les frameworks

Nous avons vu le fonctionnement de OSGI dans ses principes généraux et un peu plus dans le détails sur les mécanismes qu’il met en oeuvre pour l'exécution des bundles, des services et de leur interconnexion. Dans cet article, un peu plus court j'espère, nous allons un peu plus nous intéresser à ses implémentations [osgi-impl], leur fonctionnalité et contenu et leur intégration dans les outils JEE standard.

Implémentation

Les implémentations du framework OSGI ne sont pas légion, alors bien sur il existe une implémentation de référence fourni par l’OSGI Alliance mais il est bien précisé que celle ci n’est à utiliser qu’à titre d’exemple et ne pourrait être exploité en production car non optimisé. [OSGI-impl-ref]

Heureusement, grâce à son “grand âge”, OSGI a su intéresser des projets qui ont porté quelques implémentations associé à des versions plus ou moins divers d’OSGI. On peut ainsi en note 4 principales.

samedi 26 janvier 2019

La haute disponibilité, les Webservices et JMS dans weblogic

Un article court aujourd'hui pour parler d'architecture JEE et de haute disponibilité dans le cadre JMS.

Nous avons déjà parlé du fonctionnement de JMS mais nous n'avons pas forcement traité la question de la haute disponibilité. Mais qu'est ce que la haute disponibilité?

La haute disponibilité [HD] est la capacité d'un système a fournir un service selon un taux de disponibilité pre-déterminer.

Cela semble un peu de la paraphrase mais cela se traduit par quelles solutions doivent ou peuvent être mises en oeuvre afin de garantir le rendu d'un service par un système?

Pour répondre a cette problématique, il existe une approche simple, la duplication. il suffit de fournir le service de manière répliquée de façon à palier à des éventuelles erreurs et crash.

Dans le cadre des systèmes a base de web-services, souvent la haute disponibilité est couplé a des systèmes de répartition de charge [weblogic-WS-LB]. Le flux http/https est adressé sur un load-balancer qui a pour charge de rediriger ces flux successivement sur les différents serveurs/containeurs d'un cluster construis pour rentre le service attendu.



jeudi 24 janvier 2019

OSGI : Architecture

Nous avions vu dans un précédent article ce qu'était OSGI dans ses grandes lignes et ses principaux concepts [uetteu-osgi]. Dans celui ci, je vous propose de rentrer un peu plus dans le côté technique de cette technologie en détaillant globalement les utilisations de celle ci (surtout pour rappel), d’identifier son écosystème et ensuite de passer en revue la construction des bundles, leur constitution, leur cycle de vie et la déclaration et consommation des services.

À la suite de cela, nous nous intéresserons alors aux différents implémentations du framework réalisé au fil de ces dernières années pour enfin étudier (sommairement) leur différentes intégrations au sein des serveurs d’application Java les plus connu (à notre insu)

Architecture: Vue d’ensemble

Nous avions vu dans ce dernier article [uetteu-osgi] que OSGI était un framework Java modulaire orienté service permettant la modélisation et l'exécution de composants nommés bundle.

Ils permettent à mise en oeuvre d’application dans des contextes d'équipement à ressources limitées, s’appuient sur un modèle de collaboration utilisant une registry pour le partage de services et facilitant l'accès à ces derniers pour les consommateurs.

OSGI permet aussi une gestion à chaud de ses bundles offrant ainsi la possibilité de chargement, mise à jour et déchargement de fonctionnalité dynamiquement sans interruption de service.

Enfin OSGI offre un cycle de vie fourni un cycle de vie à ces bundles et services (que nous verrons dans un des chapitres suivant) permettant la mise en oeuvre d’une gestion intelligente des fonctionnalités mis en ligne.

C’est pour ces différentes raisons que OSGI est aujourd’hui intégrée par défaut dans la grande majorité des serveurs d’applications JEE permettant l’ajout de fonctionnalité java standard de manière plus aisé et ce même dans un contexte JEE.

Environnement d'exécution

De par son côté modulaire, OSGI offre donc la possibilité de construire des applications via une logique de puzzle où de briques, constitué selon des niveaux fonctionnelles différentes. Cette approche a donc permis de constituer un catalogue riche et varié de bundles offrant une multitude de services métiers et ou technique [tuto-osgi-oscar].

On trouvera ainsi facilement sous la forme de bundle des

  • services de base permettant l’utilisation de logs
  • bundle de gestion de configuration
  • bundles de gestions de Préférences
  • Services HTTP (e.g :servlets, ou Spark [uetteu-spark]))
  • Gestion des utilisateurs
  • Parseurs XML
  • Gestion de droits,
  • Politique de sécurité
  • Monitoring
  • de l'intégration JEE [integ-jee]



vendredi 28 décembre 2018

OSGI : Concepts généraux


Aujourd’hui nous allons parler d’un framework qui me tient à coeur: OSGI. Cela faisait un moment que je voulais écrire un article sur celui ci mais beaucoup d’autre sujet, se sont trouvé être plus intéressant sur le moment.

À vrai dire, OSGI est clairement très intéressant mais l’utilisant depuis déjà près de 8 ans, malgré l'intérêt qu’il a intrinsèquement, il ne porte plus pour moi ce goût de nouveau que peuvent avoir les sujets comme l’IA... , c’est évident.

Pourtant voilà, je me suis dit, il est temps de faire le point sur le sujet et de le mettre un peu plus sous les projecteurs, car mine de rien, quasiment tout le monde l’a un jour utiliser, mais très peu de gens le savent!

Mais repartons du début!

Historique

OSGI [OSGI], [wikipedia] ou Open Service Gateway Initiative est un framework de gestion de composants et de services. Initialement prévu pour le monde de l’embarqué (si si ^^), il a été utilisé par des constructeur comme Volvo, BMW ou encore Cisco et s’emploie dans les produits logiciels à destination du monde de la domotique et des systèmes de sécurités

Nous le verrons plus en détail mais pourquoi OSGI? parce que ce framework est léger (en dehors de la JVM) et permet le chargement et le déchargement de ses librairies à chaud tout en facilitant la manipulation de ces dernières dans des versions différentes simultanément.

Issu de la JSR 8 [JSR8], OSGI a été créé dans les années 2000 et a évolué régulièrement. Ainsi aujourd’hui la spécification OSGI en est à la version 7 [OSGI-V7] avec une implémentation de référence fourni par l’Alliance OSGI qui ne doit pas être considéré comme une version de production mais “juste de références”. Ainsi différentes versions open sources ont été implémenté pour répondre à des besoins plus techniques et se sont accaparé ces différentes versions des spécifications comme equinox [equinox], knoplerfish [knoplerfish], concierge [concierge] ou encore felix [felix].

Aujourd’hui la spécification 7 de OSGI forme un pavé de plus de 1000 pages de documentation [OSGI-V7-CORE] et il nous est impossible d’en faire un résumé exhaustif ici cependant dans cet article nous tâcherons de passer en revu les concepts pivots de OSGI pour en comprendre les mécanismes clefs puis nous nous intéresserons aux différentes implémentations ainsi que leur intégrations dans les frameworks plus classique (mais qu’on sait pas que OSGI est dedans…. O_o)

OSGI concepts généraux

OSGI est donc un framework Java. Conçu il y a près de 18 ans, celui ci est un peu partout sans que personne ne le sache vraiment. On le trouve dans la plupart de nos serveurs d’applications JEE, jusque dans nos IDE comme eclipse qui à fondé sa architecture dessus… si si…

Bien sûr ce n’est pas parce que quelque chose est utilisé partout que forcément c’est bien…. c’est vrai on le voit tous les jours avec le framework Spring! non blague à part (ou pas), OSGI est partout mais pour de bonnes raisons et c’est justement sa discrétion qui en fait sa force et sa pertinence.

En effet, OSGI est un framework amenant des moyen technique de mise en oeuvre logicielle mais aussi des moyens conceptuelles, apportant avec lui quelques paradigme de modélisation simple mais efficace laissant libre le développeur de faire ce qu’il veut tout en lui garantissant plus de souplesse à son application.

Il fournit pour cela une implémentation à deux paradigmes importants en développement logiciel:

  • la modularité qui permet la gestion et l’articulation logique des éléments de l’application
  • les services qui fournissent les moyens de donner une opérationnalitée à ces éléments en leur donnant du sens.

La modularité dans OSGI

Sans aller trop loin dans le débat de la modularité [serv-side], on rappellera quelques principe de façon à poser ce à quoi nous attendre dans OSGI

La modularité est une approche de conception permettant la séparation des préoccupations, que celles-ci soient fonctionnelle, ou technique.

Bien sur il existe différents degrés de modularité et celle-ci s’appliquant sur la solution logicielle à des niveaux très variés.

Il est ainsi possible de concevoir de façon modulaire tant au niveau de l’architecture système que de l'architecture logicielle. Quel que soit l’objectif métier, le but est de permettre de scinder les problématiques et amener du découplage facilitant ainsi: la réalisation, le test, la compréhension, la maintenance, la mise à jour, etc...



Pour mettre en oeuvre de la modularité dans une architecture, il existe divers solutions et implémentations: certains design pattern comme l’observateur [observ], l’association du pattern proxy et factory [invochand] ou encore l’utilisation de contrat de services avec des interfaces et des API comme illustré ci dessus.

OSGI propose une autre alternative en se situant à la croisé des chemins de ces approches. Nous en avions parlé dans l’article [whriteboard]. En résumé, la modularité consiste en la construction de composants interdépendants via des interfaces (API). Des lors, l’utilisation d’un module par un autre passe par une api et masque donc l’identité du composant réellement utilisé, c’est le principe du masquage de l'implémentation permettant ainsi découplage, réutilisation, capacité à être testé etc…

Cependant, on constate une limite a l’utilisation des contrats de service et des API : il faut etre capable de re-associer les composants interdépendants [serv-side]. Il faut pour cela utiliser des patterns comme la Factory et au final déplacer le couplage vers la factory [whiteboard].


Alors bien sur il existe d’autres approches pour répondre à cette problématique avec les framework d’IoC comme Spring (implémentant le pattern Hollywood [hollywood]) utilisant des xml ou des annotations. Pourtant ces solutions sont assez peu satisfaisantes car elles confient les détails d'implémentations à un acteur tiers qui aura la charge de faire communiquer les composants entre eux sur la base d’une description donné statiquement. Finalement cela re-créera un couplage car si en effet dans Spring (par exemple) on spécifie la dépendance d’un composant via une API et des interfaces, il faudra lui spécifier un à moment l'implémentation qui y répondra et cela de façon statique par configuration.

Le pattern Broker

OSGI fournit une alternative en utilisant le pattern Broker [broker] permettant, au travers d’un registre de bundle (nom des composants ou modules OSGI) et de service, de déporter le couplage en dehors de la préoccupation des composants mis en interaction.

Il s’agit avant tout d’un pattern d’architecture (non d'implémentation) qui classiquement s’utilise dans le cadre de service de messagerie comme JMS mais qui ici se focalise sur la mise en collaboration des bundles entre eux, à la demande, et ce géré par le registre.

Dans sa mise en oeuvre, un ensemble de composants (les bundles) vont s’enregistrer auprès du registre comme fournisseur de services liés à différents contrats d’interfaces. Ensuite, par l'intermédiaire du registre, ils seront appelé par d’autres bundle ayant besoin des services remplissant les contrats d’interfaces souhaités.

Dans ce principe, aucun bundle ne se connait directement, tout passe par le registre qui aura à gérer l’ensemble des services offerts et les clients qu’il faudra rediriger vers les bonnes implémentations.


Les services

OSGI est une implémentation du pattern Broker. Il s’agit donc en réalité d’un framework permettant la conception logicielle de façon modulaire mais et surtout de construire des applications selon une logique orienté service.

Ainsi comme nous venons de le voir la modularité va nous amener à séparer les préoccupations, les services vont en plus nous amener à réfléchir nos bundles selon le rôle qu’ils ont à mener dans notre application de façon à en exposer juste et seulement leur valeur ajouté.

L’idée est la encore et toujours la modularité, mais en ayant une forte décomposition, on maximise alors le re-use car un service implémentant un contrat de service pourra être mis à disposition par le registre à tous les bundles en ayant le besoin.

Vous allez dire mais ça Spring le fait déjà au final le registre, c’est le fichier xml de Spring.

Effectivement mais OSGI va plus loin:

  • D’une part, l’utilisation du registre va autoriser un bundle à consommer un service à la demande et de s’en défaire, le couplage entre les bundles est dynamique et non permanent.
  • La conséquence du point précédent que nous détaillerons plus loin dans l’article est que cela permet la mise en ligne des bundles sans que ces derniers n’aient eu le besoin de résoudre à leur chargement toute leur dépendance et service.
  • Ceci nous amènera alors à la possibilité de gérer des versions concurrente d’un même service pour faciliter leur mise à jour à chaud.

Avec OSGI, la gestion des services par le registre des bundles nous laisse entrevoir quelques fonctionnalités dont nous n’avons pas vraiment l’habitude. Dans un projet classique, généralement nous pensons notre application comme un tout unique dont les éléments, librairies et services, devront évoluer conjointement. Mais avec OSGI, cette vision limitative devient caduc et il faudra penser l’application comme un système en perpétuel mutation dont les éléments nouveau côtoient des éléments anciens et dont les services seront utilisés selon le besoin.

Gestion des dépendances

Pour permettre des mécanismes de gestion à chaud des bundles et de la consommations dynamiques des services, OSGI va donc fournir un certain nombre de concepts focalisé sur une gestion un peu particulière des dépendances.

Cette gestion des dépendances va s’exprimer selon deux types [10min]:

  • les dépendances statiques
  • les dépendances dynamiques

Statiquement

La gestion statique des dépendances dans OSGI est assez similaire à la gestion des dépendances Java réalisé avec le classpath à ceci prêt que celui ci est plus stricte car embarque avec les lui le detail des versions impliqué dans la dépendance.

Cela paraît dans un premier temps très contraignant cependant cela permet en fait de faire vivre au sein du framework deux versions distinctes d’une même dépendance, laissant alors au composant qui en ont besoin d’utiliser celle avec laquelle il sera le plus en phase.

Ce type de dépendance se déclarent au sein du manifest java décoré et adapté au formalisme OSGI (nous verrons cela plus en détails dans le chapitre sur les bundles).

Ainsi les bundles lorsqu’ils seront chargé par le framework OSGI (on verra plus tard mais il s’agit de la phase d’installation) devront trouver dans leur classpath ou dans les classloader du framework les dépendances apportées par les autres bundles dans les versions attendues


Dynamiquement

Une fois installé, un bundle apporte un ensemble de dépendance statique, cependant, pour créer un minimum de couplage, il est préférable de s’appuyer autant que faire se peut sur le pattern broker.

Ainsi pour cela le framework OSGI nous amene à construire des bundles définissant des contrats des services ne contenant que des informations spécifiques aux contrats de services.

Ainsi ces contrats seront ensuite implémentés par un autre bundle qui aura la charge de l'implémentation du contrat de service. Ainsi, ce bundle s'enregistrer auprès du registre et lorsqu’un autre bundle demandera au registre OSGI un service conforme au contrat de service défini dans le bundle contrat alors le registre fournit l'implémentation.

L'intérêt de cette approche est qu’il est possible alors de proposer divers implémentation d’un même contrat de service.


Conclusion

Nous avons dans les grandes lignes les principes généraux de OSGI, son paradigme de modélisation modulaire et orienté service.

L'intérêt de son utilisation est double, d’une part de fournir une solution réelle de couplage des modules mais aussi la capacité de faire évoluer une application dynamiquement tout au long de son cycle de vie et ce, “à chaud”.

Il peut être intéressant maintenant d’en parcourir l’utilisation dans le concret (dans le prochain article sur OSGI) afin de mieux appréhender ses contraintes techniques.

Références

jeudi 8 novembre 2018

Design Pattern : Whiteboard

Pourquoi le pattern whiteboard?

Le pattern Whiteboard [1, 2] est un pattern un peu spécifique, il à la particularité d'être intimement associé à la technologie OSGI [3, 5] et comme il était question dans ce blog de parler de ce framework, nous voici donc avec une petite introduction de ce dernier via ce pattern de conception.

Au delà du prétexte de l'écriture d’un article introductif à OSGI, ce pattern pattern à bien entendu une raison d'être qui lui est propre: proposer une alternative raisonnable au pattern listener dans la conception de logiciel à base de microservice comme le permet OSGI [4].

On entrevoit donc ici les raisons de l’utilisation du pattern mais pour etre plus precis, nous regarderons avant cela les concepts de base de OSGI afin d’en comprendre les besoins et avant de détailler plus en avant le pattern whiteboard, nous regarderons pourquoi le pattern listener n’est plus satisfaisant dans certaines situations.

Techno OSGI dans les grandes lignes

La technologie OSGI ou Open Service Gateway Initiative est un framework Java pour la construction d’application à base de composants et de services. Il s’agit d’un framework ayant pour vocation initial la réalisation d’application à taille réduite où la gestion mémoire est millimétré.

Il permet techniquement de gérer simultanément des librairies java évoluant dans des versions différentes ainsi que de charger et décharger ces librairies dynamiquement sans nécessiter le redémarrage de la JVM. Par contre, pour permettre ces capacités, OSGI “impose” (mais en fait c’est un bien) un paradigme de modélisation impliquant la construction de nos application selon une architecture un peu spécifique à base de composant (les bundles) et de services.

Avec cette petite introduction, on perçoit rapidement l'intérêt de ce framework! Nous y reviendrons plus tard, nous en avons vu l’essentiel pour l’instant. Il faut surtout en retenir que OSGI nous permet de construire des applications modulaires à base de composants et de services. Dédié initialement à l’embarqué, il est sortie rapidement de son contexte d’utilisation initial et s’est alors confronté aux méthodes et techniques de construction des architectures logiciels classiques.

Pourtant avec une architecture tel que proposée par OSGI, ce pattern comporte de nombreuses limites.

En effet, dans une architecture à composant ou les dépendances entre composant ne peuvent être forte, il est nécessaire de permettre à deux objets de communiquer sans forcément qu’ils aient connaissance de l’un et de l’autre directement.

Pattern Listener et limites

Entre autre, le cas du pattern Listener est caractéristique car dans le cadre de son utilisation dans le cadre OSGI, il comporte quelques limites.

Nous avons traité le pattern listener dans un autre article [6], je n’y reviendrais pas ici. disons simplement que ce pattern est un pattern d’architecture et comportemental permettant le découplage d’un observateur et d’un observer tout en formalisant son moyen de communication via un objet de type événement. Il s’agit en fait du pattern observateur mais simplifié.

Ce pattern est souvent utilisé pour sa nature événementielle dans le cadre de la gestion des IHM. Ainsi, par exemple, lorsque utilisateur sollicite la souris de son ordinateur, le contrôleur associé va générer des événements permettant de suivre ses déplacements. L'utilisation du pattern listener est en première approche une solution intéressante pour traiter ces événements surtout lorsque les sources possibles sont multiples. Pourtant c’est là sa limite également. Car alors si ces sources produisent de multiples événements simultanément alors le système peut être soumis à un “EventStorm” [1] amenant à une utilisation élevée de la mémoire et du CPU, perdre gravement en performance et dans le pire des cas conduire à un crash.

Whiteboard pattern

Le pattern Whiteboard est une solution apportée comme alternative au pattern listener dans le cadre du framework OSGI.

Il est intimement lié à OSGI cependant comme nous verrons ce framework par la suite il me semble plus pertinent d'éviter d’entrer dans trop de détails d'implémentation lié à cette technologie. Ainsi nous nous attacherons à une présentation d’un modèle abstrait du pattern (sous la forme d’un type PIM, Plateform Independant Model dans le MDA [7])

Ce pattern propose de découpler la source des événements du listener en introduisant un objet supplémentaire entre les deux servant de registre et transformant la relation entre les deux éléments par une relation de service et de consommateur de service.

Ce qui servait donc de listener devient un composant fournissant un service qui sera enregistrer dans un registre. La source des événements aura alors la tâche de demander au registre le service adéquat afin de pouvoir lui transmettre les événements produits.




L'intérêt de l'approche en ajoutant ce registre qui finalement réalisé la réification de la relation listener/sources des événements est de permettre de contrôler cette relation et son utilisation par la source des événements.

Il va être alors possible :
  • de réaliser du monitoring sur le flux d’informations voir même de le debugger
  • de rendre indisponible le service du listener si celui ci est trop utilisé et implique une consommation des ressources trop importante
  • d’adjoindre des droits spécifiques d’utilisations en ajoutant sur le registre une couche de sécurité et des permissions afin de ne pas le rendre disponible à n’importe quel consommateur du service venu
  • injecter des propriétés spécifique pour customiser le mapping (comme par exemple pour préciser un quota en événement par seconde à traiter ou pour proposer une taille de tampon d'événements, etc…)

Exemple

Pour illustrer ces mécanismes voici dans un contexte hors OSGI ce qu proposerait une implémentation du pattern listener (observateur) et ensuite son équivalent dans la philosophie du pattern Whiteboard. On précise ici que l’on reste dans une implémentation de type PIM afin de ne pas perturber la compréhension du pattern avec les spécificités technologiques du framework OSGI

Avec Listener


package listener

class Event{
    String message

    Event(String m){
        this.message=m
    }
}

interface IObserver{
    def update(Event e)
}

interface IObserved{
    def notifyAll(Event e)
}

class TrucQuiEcoute implements IObserver{
    def update(Event e){
        println("Reception d'un message")
        println(">>"+e.message)
    }
}

class TrucQuiFait implements IObserved{
    List obs=new ArrayList<Observer>()

    def notifyAll(Event e) {
        for( Observer o in obs){
            o.update(e)
        }
    }

    def makeSomething() {
        def e = new Event("Ceci est le message")
        println("Envoie d'un message")
        this.notifyAll(e)
    }
}


def ob=new TrucQuiEcoute()
def obd=new TrucQuiFait()
obd.obs.add(ob)
obd.makeSomething()

Avec Whiteboard


package whiteboard

interface IService{
    def serve(Event e)
}

class ServiceRegister{
    Map services=new HashMap<String,IService>()
}

class Event{
    String message

    Event(String m){
        this.message=m
    }
}

class TrucQuiEcoute implements IService{
    def serve(Event e){
        println("Reception d'un message")
        println(">>"+e.message)
    }
}

class TrucQuiFait implements IService{
    ServiceRegister register;

    TrucQuiFait(ServiceRegister register)
    {
        this.register=register;
    }

    def serve(Event serviceNameEvent) {
        def e = new Event("Ceci est le message")
        println("Envoie d'un message")
        this.register.services.get(serviceNameEvent.getMessage()).serve(e)
    }
}

def reg=new ServiceRegister()
reg.services.put("TrucQuiEcoute",new TrucQuiEcoute())
reg.services.put("TrucQuiFait",new TrucQuiFait(reg))

reg.services.get("TrucQuiFait").serve(new Event("TrucQuiEcoute"))

Conclusion

Voilà nous avons fait le tour de ce pattern un peu spécial enfin, surtout un peu spécialisé, qu’est le pattern Whiteboard. Celui-ci est très associé à OSGI mais il peut se comprendre sans et surtout mieux comprendre certains mécanisme de ce framework que nous verrons dans un prochain article.

Références

[1] https://www.osgi.org/wp-content/uploads/whiteboard1.pdf
[2] https://en.wikipedia.org/wiki/Whiteboard_Pattern
[3] https://www.osgi.org/
[4] https://enroute.osgi.org/FAQ/400-patterns.html
[5] https://www.theserverside.com/news/1363820/The-Whiteboard-Pattern-for-OSGi
[6] https://un-est-tout-et-tout-est-un.blogspot.com/2017/11/design-pattern-observateur.html
[7] https://laine.developpez.com/tutoriels/alm/mda/generalites-approche-mda/



samedi 17 février 2018

IA : Petit point de littérature

Petit retour sur quelques lectures du début d'année .

Un premier livre qui donne des bases théoriques et techniques complètes en machine learning, pour ceux qui aiment le python je recommande vivement, et pour les autres aussi car Scikit learn est un incontournable, donc c'est aussi une bonne occasion de se mettre au python.

A destination d'un public avec un minimum de bagages techniques...

Machine Learning avec Scikit-Learn




Le second livre est traite du deep learning. Honnêtement, un peu déçu, l'ouvrage s'adresse vraiment a qui ne connait vraiment rien sur le sujet, (même pas qu'il nécessite de maîtriser quelques rudiments de calcul matriciel), en même temps, il est vraiment que ce n'est qu'une "introduction". 

Je conseille aux pures novices, qui étudient le sujet par curiosité.

Comprendre le Deep Learning




Un troisième ouvrage sur lequel je ne fondais pas beaucoup d'espoirs... Et grosse surprise, un ouvrage bien construit et complet, suffisamment abstrait sur les sujets du Dig Data, du ML et des rudiments du DL pour conclure que : 
  • tout manager se doit de le lire pour comprendre le monde qui se profile ces prochaines années 
  • suffisamment technique pour orienter les techos sur les frameworks principaux des ces domaines avec la bonne dose d'explications pour en comprendre les utilisations et les architectures types 

Un indispensable je pense pour celui qui veut entrer dans ces trois sujets a la fois et en comprendre les tenants et aboutissants.

Big Data et Machine Learning


Voila un petit aperçu de mes dernières lectures, ces dernières me serviront pour les prochains articles  qui traiteront de l'IA mais avant il reste deux à traiter
Mais je reviendrais sur ces deux livres

mardi 30 janvier 2018

Test d'IHM : fest-util

Effectuer des tests unitaires est une tâche indispensable mais qui peut souvent s'avérer un vrai casse tête lorsqu’il s’agit de traiter des IHM.

En Java standard il existe une librairie de test dédiée au IHM de type client lourd pour les API swing et awt qui s’appele Fest [1] [3]. Celle est vraiment concu pour etre simple et logique en utilisant les noms des éléments de l’IHM pour se mapper sur leur interfaces de fonctionnement.

Pour l’utiliser il suffit de tirer l'artefact suivant:
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-util</artifactId>
<version>1.1.6</version>
<scope>test</scope>
</dependency>
Pour l’utiliser il reste à définir une classe de test classique JUnit héritant de la classe FestSwingJUnitTestCase dans laquelle il faudra initialiser un robot Fest et le donner à un objet de type FrameFixture qui va se charger de piloter le robot afin que celui ci parse et effectuer les interaction adéquate sur notre IHM.

Avant cela, Pour que le robot soit capable de parser notre IHM il faudra par contre indiquer a Fest sur quel IHM il doit faire ses actions (grâce a un GuiQuery). On spécifie alors une méthode statique d’initialisation dédié dans laquelle nous instancierons notre IHM:
@RunsInEDT
private static MainFrame createNewEditor(BundleContext context) {
final GuiQuery<MainFrame> query = new GuiQuery<MainFrame>() {
@Override
protected MainFrame executeInEDT() {
MainFrame app = null;
try {
app = new MainFrame(context);
} catch (final TcOsgiException e) {
e.printStackTrace();
}
return app;
}
};
return GuiActionRunner.execute(query);
}
Du coup, il nous faudra initialiser dans un setUp notre environnement de test contenant le FrameMixture:
@Override
protected void onSetUp() {
try {
BundleContext context = Mockito.mock(BundleContext.class);
editor = new FrameFixture(robot(), MainFrameTest.createNewEditor(context));
editor.show();
} catch (Exception e) {
e.printStackTrace();
}
}
Grace a cela, il ne nous restera plus qu’a declarer les actions que l’on souhaitera faire sur l’IHM dans des tests spécifiques comme on le ferait dans un test unitaire classique sauf que la nous allons scénariser les actions:
@Test
public void profilCreationSelection() {
editor.menuItem("Select MorphMath Action").click();
editor.comboBox("combo1").selectItem("dilatation").click();
editor.menuItem("GO").click();
System.out.println(new File(".").getAbsolutePath());
editor.fileChooser().fileNameTextBox().setText(
"docvierge.bmp");
editor.fileChooser().approve();
Thread.sleep(500);
editor.close();
}
A noter qu'à ce niveau d’abstraction, nous ne sommes plus vraiment en train de faire des tests unitaires mais plutôt des tests fonctionnels mais cela n’a pas forcement d’importance dans notre cas (a noter malgré tout que l’approche est particulièrement adapté à la mise en place de test pour vérifier des cas d’utilisation particulière en lien direct avec le besoin utilisateur)

Voila un petit aperçu de Fest et de ses capacités pour des tests d’IHM. Point particulier a prendre en compte lors de l'exécution des tests: ces derniers sont réalisés avec une IHM visible vous permettant de voir quels sont les actions et mouvement de souris réalisées pour faire le test. Cela est clairement intéressant mais comporte un inconvénient majeur, vos tests ne fonctionnent pas sans environnement graphique comme dans un serveur d'intégration continu. Typiquement vous aurez une erreur du type (dans Travis [2] par exemple):

PM org.fest.swing.monitor.WindowStatus <init>
WARNING: Error ocurred when creating a new Robot
java.awt.AWTException: headless environment
at java.awt.Robot.<init>(Robot.java:91)
at org.fest.swing.util.RobotFactory.newRobotInPrimaryScreen(RobotFactory.java:35)
at org.fest.swing.monitor.WindowStatus.<init>(WindowStatus.java:58)
at org.fest.swing.monitor.WindowStatus.<init>(WindowStatus.java:51)
at org.fest.swing.monitor.WindowMonitor.<init>(WindowMonitor.java:51)
at org.fest.swing.monitor.WindowMonitor$SingletonLazyLoader$1.executeInEDT(WindowMonitor.java:134)
at org.fest.swing.monitor.WindowMonitor$SingletonLazyLoader$1.executeInEDT(WindowMonitor.java:132)
at org.fest.swing.edt.GuiQuery.run(GuiQuery.java:41)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Pour résoudre ce problème il vous suffira d’utiliser xvfb (un server X11) [4] . Comme décrit dans [5], cela permet de simuler un environnement graphique. (ou un autre exemple [6]).

References:

[1] http://www.vogella.com/tutorials/FEST/article.html
[2] https://travis-ci.org/
[3] http://tuhrig.de/automated-ui-testing-with-swing-fest/
[4] https://www.x.org/archive/X11R7.6/doc/man/man1/Xvfb.1.xhtml
[5] https://docs.travis-ci.com/user/gui-and-headless-browsers/#Using-xvfb-to-Run-Tests-That-Require-a-GUI
[6] https://gist.github.com/cecilemuller/764afa5d4c67e17741d9bc258b45cdc1

dimanche 21 janvier 2018

IA : Les systèmes experts, Drools

Cet article est le premier d’une longue série sur l’intelligence artificielle. Je n’ai pas introduit cette dernière mais je n’y manquerai pas dans un article futur. Je passe donc sur cela pour m’intéresser directement à un axe complet de l’IA que sont les systèmes experts [1] [2].

Les systèmes experts sont ce que l’on appelle dans le domaine de la modélisation, le modèle des comportements d’un expert du domaine. Son rôle est de procéder de la même manière que l’expert afin d'en reproduire l’analyse.

Un système expert va donc consolider la connaissance de l’expert du domaine pour procéder à des traitements conformes à ceux prescrits par ce même expert. Deux concepts clefs des systèmes experts sont identifiables alors:

  • une base de connaissances
  • des règles d'inférences

Selon ces concepts, un système expert croise alors les connaissances avec les règles dans un moteur d'inférence qui peut alors produire soit des nouvelles connaissances, soit de nouvelles règles ou les deux.



jeudi 2 novembre 2017

Evolution Java 8

Nous voila arrivé a la dernière version officielle de Java... Enfin officiel, en fait non car Java 9 vient de sortir mais avant qu'elle ne devienne la référence, Java 8 a encore quelques mois devant elle.
Voyons ses évolutions principales et moins principales.

L’implémentation par défaut des interfaces, les defender methods

Cette feature n'est pas forcement celle que l'on doit utiliser, a priori, celle ci est surtout l'objet d'un besoin de compatibilité des API avec d ancienne version de celle-ci en fournissant des comportements sans avoir a les implémentés.

1
2
3
4
5
public interface InterfaceAMoi {
    default void test(){
        System.out.println("a implementer");
    };
}

Bon ils est vrai que sur le fond c'est probablement l'une des grosses surprises de Java 8, car une interface ne définie qu'une interface de réalisation, voici que celle ci va fournir une comportement par défaut. Alors bien sur une interface n'est pas une classe et ne peut donc que manipuler par défaut que le comportement mais on peut se demander si nous ne risquons pas de retomber dans les problèmes du c++ et des héritages multiples que permettait d’éviter les anciennes interfaces. Il va falloir rester très prudent avec cette nouvelle feature de Java. L'exemple de ce probleme est tres bien expliqué dans cet article.

En parlant d'interface, on peut noter que l'on peut maintenant y définir des méthodes statique. Cela est plutôt mineure comme avancé mais cela va permettre de ne plus avoir a construire des classes a constructeur privé juste pour définir des bibliothèques de fonctions utilitaires.

Lambda expressions

Les lambda expressions sont la grosse evolution de Java 8. Issues des approches fonctionnelles, elles permettent la définition a la volée d'une fonction directement utilisable. Son intérêt et globalement la simplification du code qui jusque la devait être écrit sous la forme de classe interne anonyme comme on pouvait le faire avec Swing.

Donc avant on écrivait ceci:

1
2
3
4
5
6
7
public static void main(String[] args) {
  Runnable c=new Runnable(){
    @Override
    public void run() {
      System.out.println("J'implemente ma classe annonyme");
    }};
}

Désormais on écrira ceci:

1
2
3
4
5
public static void main(String[] args) {
  Runnable c=()->{
     System.out.println("J'implemente ma lambda expression");
  };
}

Bien sur il existe des contraintes. La première est qu'une lambda expression se construit sur la base d'une interface (pas d'une classe abstraite) ne comportant qu'une seule méthode. Voila pourquoi on peut utiliser les lambda expression a partir de l'interface Runnable.

Donc si on définit une interface :

1
2
3
public interface Toto {
    public void toto();
}

et on l'utilise comme suit

1
2
3
Toto c=()->{
      System.out.println("J'implemente ma lambda expression");
 };

A noter que l'utilisation des classes anonymes n'a jamais été une bonne pratique, on peut donc se demander si les lambda expression en sont une puisque finalement elles ne sont qu'un sucre syntaxique permettant de simplifier l’écriture et la lecture du code (pour ceux qui ont l'habitude de les manipuler....)

A mon sens, avec ce que l'on vient seulement de découvrir, les lambda expression ouvrent la possibilité d'une utilisation plus souple et plus dynamique de comportement en facilitant l'emploi de certains pattern de conception comme les patterns décorateurstratégie, médiateur ou encore de type fabrique ou commande. Mais pour comprendre tout cela il faudrait regarder plus profondément  dans package java.util.function.

java.util.function

Ce package contient un grand nombre d'interfaces fonctionnelles mais 3 principales sont a citer car participant de façon de façon générales au sein de tous types d'approches fonctionnelles:

  • les predicats pour tester les functions
  • les consumers pour appliquer des fonctions
  • les opérateurs pour combiner des opérations et des éléments

A noter pour les logiciens que ces concepts modélisent de façon générale des logiques de tous types (mais je reviendrais sur ces points dans des articles dédiés aux logiques)

Les références méthodes

Elles fonctionnent comme des lambda expression mais permettent de simplifier l’implémentation d'une classe anonyme. In fine l'utilisation de ce mécanisme permet d'appeler une méthode de classe ou d'instance de façon groupée en réalisant une lambda expression de façon implicite

au lieu de:

1
2
3
4
5
6
7
List<String> l = new ArrayList<>();
l.sort(new Comparator<String>() {
  @Override
  public int compare(String o1, String o2) {
    return o1.compareTo(o2);
  }
});

on aura:

1
2
List<String> l = new ArrayList<>();
l.sort(String::compareTo);

Ce qui indéniablement simplifie l’écriture lorsque l’implémentation elle même est simple....et commutative le cas échéant....

A noter en digression sur ce chapitre que java 8 offre maintenant la capacité de tri parrallele sur les tableaux:

1
Arrays.parallelSort(myArray);

Dans d'autres cas ca sera plus simple:


1
l.forEach(String::trim);

Stream methode

Les streams permettent le traitement de listes sous la forme d'un flux un peu comme le ferai un iterator mais orienté fonctionnelle. Ainsi naturellement, les lambda expressions vont s'appliquer dessus au travers de divers activités telles que les filtres.

Les streams vont fournir également des capacités sur le processus de traitement en permettant soit de séquentialisé les opérations (par exemple si l'ordre des éléments a une importance) ou d’être parallélisé si l'ordre n'a pas d'importance et que les données peuvent être partitionnées.

Par exemple pour récupérer la sous-liste des chaines démarrant par S dans une liste de chaînes:


1
2
List<String> l = new ArrayList<>();
List<String> filtredl=l.stream().filter((s)-> s.startsWith("S")).collect(Collectors.toList());

L'incorporation de Nashorn

Apres l'ajout d'une API de scripting et d'un interpreteur javascript (Rhino) dans Java 6, il aura fallu attendre Java 8 et l'integration de Nashorn pour beneficier d'un moteur JavaScript du type de NodeJS. L'article de Soat en donne une bonne description.

Time API

Java 8 intègre une refonte complète de l'API gérant le temps car celle ci manquait de cohérence générale. Ainsi avec cette mise a jour, Java 8 propose une API fournissant un ensemble de classes plus rationnelles, thread-safe et immutable.

rationalisant les besoins généraux de la gestion du temps et des dates en les . Je n'entre pas dans le détail car l'article suivant fourni déjà tout les exemples nécessaires a une bonne compréhension et si voulez plus d'info, cet article ci vous conviendra peut être mieux.

Les annotations

Dans la liste des améliorations on notera la possibilité de placer plusieurs fois sur le même éléments une même annotation et également de pouvoir en placer sur les types. Ceci aura pour intérêt, en donnant au compilateur les framework de vérification adéquat, d'ajouter des contraintes sur le code afin d'en garantir une meilleur qualité.

Java IO

On notera également quelques plus sur l'API IO introduite avec Java 7 pour une manipulation des fichiers en cohérence avec l'introduction des streams.

Les verrous  stamped

Après les verrous de lecture ecriture venus avec la Java 7, Java 8 introduit les verrous stamped. Autant si les premiers sont d'une utilisation tres simple, ils soufrent de problème de performances, ainsi, les seconds seront a optimiser afin de satisfaire aux éventuels problème de concurrence. Par ce fait, ils sont par contre plus compliqué a utiliser.

On entrera dans les details de la programmation multi-thread dans un autre article. Cependant je vous invite a lire celui-ci si vous souhaitez avancer sur le sujet.

Les concurrent Adders

Il sont la en remplacement des Atomic afin de fournir une solution de comptage concurrente et non bloquante. Tout comme les verrous en lecture ecriture, les Atomic on été intégrés dans Java 7 pour simplifier l’écriture et l’emploie de bloc synchronised sur de simple compteur (voir article) Seulement, comportant certaines limitations (de contention essentiellement), Java 8 apporte une nouvelle solution les Adders.

Process

 La classe Process se voit améliorée de trois méthodes pour vérifier l’état de vie d'un processus système, pour le détruire ou pour l'attendre. Ces méthodes complètent celles existantes de l'API JNI qui permettait de lancer des processus au sein de l'OS hebergeant la JVM.

SecureRandom

Java 8 soufrait d'un manque de securité dans la génération des nombres aléatoires pour les clefs de chiffrements. Elle offre désormais une API  stable quelque soit l'OS.

Optional

 L'api Optional est une nouvelle évolution de Java 8 dont le but est de pousser le développeur a ne plus utiliser le mots clef null comme d'un type. En effet, dans de nombreuses méthodes, il arrivait qu' il soit nécessaire de finaliser celle ci par un return null qui oblige nécessairement l'utilisateur de la méthode a préalablement vérifier la non nullité des données.

Avec Optional, on dispose d'une API permettant d’éviter de fournir un null voir de fournir une valeur par défaut adapté au type réel retourné de la méthode.

L'article suivant fournit l'ensemble des cas d'utilisation de cette classe et cet article ci décrit la nature de ce qu'est un Optional.

Attention a l'abus, Optional ne sert qu'a éviter de faire un retour de méthode null et ne s'utilise pas comme d'un Mock.... Optional ne sert qu'a contourner la nullité.

Suppression du PermGen

Avant de parler de Java 8 je vous propose de consulter le fonctionnement de la gestion memoire avant java 8 et celui ci sur l'optimisation.

Dans Java8, les développeurs vont voir disparaitre la PermGen ou permanent generation. Cet espace mémoire dédié au chargement des classes. Disparition? non quand même pas en fait, la PermGen a etre renommé en Metaspace qui va trouver sa place dans la mémoire native. En fait, depuis que la JVM est capable de charger et décharger des Classloader personnalisé, on va désormais trouver un Metaspace par Classloader permettant de charger et décharger directement dans la mémoire des classes. A noter que implémentation de Classloader personnalisé peut etre fastidieux et je recommande grandement l'utilisation d'OSGI. Mais ceci est une autre histoire.... enfin article.

Pour plus de détails n’hésitez pas a consulter cet article.

Voila, l'article sur la conséquente version Java 8 est terminer, Elle aura ete longue et pourtant je n'ai pu entrer dans trop de détails.... je tacherai de fournir quelques articles supplémentaires afin de compléter celui-ci.

Edit (06/11/2019)

Une référence utile sur la concaténation de chaînes :
https://redfin.engineering/java-string-concatenation-which-way-is-best-8f590a7d22a8

lundi 16 octobre 2017

La conception logicielle

Cet article a pour but d'introduire une série d'articles relatifs à la conception logicielle et plus généralement au développement des systèmes logiciels ou encore Génie logiciel.

La conception logicielle est entre autre une sous-activité du développement des systèmes logiciel. On la place généralement entre l'analyse des besoins et l'implantation du logiciel. Son objectif est de répondre aux objectifs suivant:

  • Maîtrise de la complexité 
  • Amélioration de la productivité et de la qualité
  • Maîtrise des coûts
  • Maîtrise de l’évolution du logiciel et de son obsolescence

Pour partir sur une définition de la conception logicielle, nous pourrions en donner celle-ci:
Processus permettant, a partir d'un besoin fonctionnel donné, l'élaboration d'un ensemble de concepts métiers et techniques reconstituant la logique du besoin en vue d'une implantation logicielle. Le produit de ce processus est l'architecture logicielle.
On voit bien dans cette définition qu'il s'agit d'une activité et qu'elle permet de caractériser des concepts qui naturellement seront associé aux éléments de l'architecture. Ainsi, sur cette base, nous pouvons donner une définition pas si évidente que ça de l'architecture logicielle:
Organisation générale d'un système en tant que tout, matérialisé pas ses composants, leurs relations mutuelles et des relations avec l'environnement, étayé par des principes guidant la conception et l'évolution du système.
Bien sur cette définition est celle fournie par l'IEEE et est donc très formelle surtout que finalement ça ne nous donne pas vraiment de clefs pour faire de la conceptions logicielles même si on en voit mieux l'objectif, on a pas encore forcement de méthode ou de processus pour mener a bien cette tache.

Ainsi divers approches existent pour concevoir un système logiciel:

  • Utilisation de patterns de conception et d'architectures qui définissent des standard de construction déjà éprouvés
  • Utilisation de frameworks consolidant des aspects métiers ou techniques 
  • La modélisation afin de rationaliser l'architecture dans une spécification plus proche des aspects d'implantation et de fournir une méthodologie pour capturer les concepts du besoin (par exemple en traitant séparément des aspects métier et aspects technique)
Voila, après avoir abordé ces quelques notions, je traiterai plus en avant des sujets évoqués comme les patterns de conception, les frameworks, la modélisation (entre autre avec l'IDM), etc...