PetalsLink DSB expliqué


Dédramatiser le Bus de Service que je développe depuis 2 ou 3 ans, tel est le but de ces quelques slides que j’ai présenté à l’équipe R&D la semaine dernière…

 

Publicités

Jouons avec le Petals Kernel et Apache CXF


Oui, à chacun sa façon de s’amuser… Je viens d’ajouter une feature dans le Petals Distributed Service Bus qui me trottait dans la tête depuis un petit moment: Pouvoir invoquer des services techniques (distants ou pas) du coeur du DSB en utilisant la couche de transport naturellement utilisée pour invoquer des services métiers (les services hostés par le bus ou liés à celui ci). Autrement dit, imaginons que j’ai un service technique qui tourne sur un noeud et que depuis un autre noeud, je dispose d’un client pour l’invoquer de façon simple mais aussi totalement transparente.

Ce que l’on pouvait faire jusqu’à présent, c’est utiliser l’API Web service exposée par le DSB pour invoquer le service pour peux que le service soit annoté comme il faut (pour rappel, cette API Web service utilise Apache CXF pour exposer automatiquement les composants Fractal qui sont annotés avec JAXWS). Bien, mais par défaut on utilise deux ports pour les communications inter noeuds: Le port utilisé par Apache CXF, et l’autre par la couche de transport du DSB (en fait c’est le cas dans Petals ESB, mais dans le DSB, la couche de transport étant par défaut une implémentation en Web service, on utilise le même port pour les deux). En allant un peu plus dans les détails, même si on utilise le même port pour les deux modules dans le DSB, ceci n’est plus vrai si une nouvelle implémentation de la couche de transport utilise autre chose que CXF (pour info, dans le DSB, une implémentation de la couche de transport en XMPP existe aussi). C’est donc la qu’on arrive a la solution d’utiliser le canal de communication du DSB pour toute invocation entre noeuds, comme on sait déjà échanger des messages avec le DSB, pourquoi s’en priver?

C’est bien beau de vouloir exposer des services, des composants Fractal, ou quoi que ce soit, si on veut rester en Java et ne pas avoir besoin de se triturer le peu de cerveau qu’il nous reste, autant penser à utiliser tout ou partie d’une solution qui existe deja. En allant dans ce sens, comme on doit au final avoir une sorte de serialization des messages, autant utiliser quelque chose qui sait deja le faire, j’ai nommé le couple inséparable JAXB+JAXWS. Ceci impliquera seulement d’annoter ses interfaces et de créer des types propres et JAXB-aware mais au final, je ne pense pas que cela soit une contrainte forte… C’est bien beau tout cela mais JAXB + JAXWS tout seul ca ne fait pas grand chose. C’est la qu’entre en jeu Apache CXF. Puisque l’utilisation de JAXWS est simple avec CXF, autant s’intéresser un peu à la bete. Pour le coup cà tombe bien, dans CXF il y a deja une notion de transport multiple: HTTP, XMPP, JMS et si on regarde bien on a même JBI (les potes de chez JonAS ont d’ailleurs implémenté un transport CXF utilisant les EJB ou un truc J2EE dans le style si ma mémoire est bonne). Tiens donc, il y a un transport JBI? Ca tombe (presque) bien, le DSB est basé sur Petals ESB qui est JBI compliant. Oui mais en fait non. J’aurais presque pu l’utiliser mais le but est d’implémenter quelque chose d’assez ‘JBI independant’. Le tout est maintenant d’implémenter un nouveau transport pour le DSB et grace au code source de CXF et à cette page http://cxf.apache.org/custom-cxf-transport.html on comprend assez bien comment faire. Dans la terminologie CXF, le client est le ‘conduit’ et le serveur est la ‘destination’. Il suffit donc d’implémenter nos propres conduit et destination pour pouvoir échanger des messages avec CXF.

Une fois CXF configuré avec nos conduit et destination, ou plutôt une fois la bonne transport factory implémentée, on devrait pouvoir faire quelque chose du style:

// 1. Initialize CXF Bus with factory
Bus bus = BusFactory.getDefaultBus();
DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class);
DSBTransportFactory petalsTransportFactory = new DSBTransportFactory();
petalsTransportFactory.setBus(bus);
petalsTransportFactory.registerWithBindingManager();

// 2. Start service
System.out.println("Starting CXF server...");
JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean();
sf.setAddress("dsb://host/serviceA");
sf.setServiceClass(HelloService.class);
sf.setServiceBean(new HelloService() {
    public String sayHello(String input) throws PEtALSWebServiceException {
        System.out.println("SAY HELLO INVOKED!");
        return pre+input;
    }
});
sf.create();

// 3. Create the client and invoke
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setAddress("dsb://host/serviceA");
factory.setServiceClass(HelloService.class);
HelloService hello = (HelloService) factory.create();
String out = null;
try {
    out = hello.sayHello(in);
} catch (PEtALSWebServiceException e) {
}

Je passe les détails d’implémentation (que j’ai eu le plaisir de faire dans un bon vieux TGV en panne entre Montpellier et Bruxelles) pour le moment, mais ce qui se passe se résume à:

  1. On configure CXF en lui ajoutant notre Transport Factory. Au niveau de l’implémentation, il y a ce qu’il faut pour que lorsque une client ou une server factory est configurée avec une adresse qui commence par ‘dsb://’, ce soit notre DSBFactory qui soit automatiquement appelée par CXF.
  2. La création du service se fait comme si on créait un Web service sur http sauf que là c’est un ‘Web service sur DSB’.
  3. Idem que pour 2 mais on génère un client qui nous permettra d’appeler le service créé auparavant.

En résultat, pour peu que le client (en 3) et le serveur (en 2) soient exécutés sur des noeuds séparés, le DSB se chargera d’acheminer la requête et la réponse comme il faut entre les acteurs et ceci de façon complètement transparente. Au niveau de l’implémentation coté kernel du DSB (ceci vaut aussi pour Petals ESB), il suffit de connaître quand même un peu le coeur pour créer des fakes de composants JBI en farfouillant dans les APIs disponibles, de savoir jouer avec le DeliveryChannel, le ComponentContext, le NormalizedMessageRouter, ajouter quelques modules de routage, savoir recevoir des messages et y répondre, et surtout implémenter le Conduit et la Destination CXF en s’inspirant de ce qui existe déjà et en mettant les doigts dans le cambouis. Pour les curieux, je vous conseille de jeter un oeil au code de CXF assez compréhensible et pas mal fait du tout.

Enfin pour étendre cela aux services techniques du coeur du DSB, il suffit, au runtime, de scanner les services disponibles offerts par les composants du kernel et automatiquement créer les services comme décrit dans l’étape 2. Chose que l’on sait déjà faire dans le DSB via le scan pour exposer les services en Web service sur HTTP avec CXF (oui toujours lui, avant je m’en prenais a Axis2…).

Et voila donc une belle et simple façon de simplifier la vie du développeur du DSB (c’est à dire moi). Il va être maintenant possible d’invoquer n’importe quoi de n’importe où avec une API Java. Pour peu que l’on plugge quelques modules au bon endroit, on peut imaginer faire des choses assez sympa: Le Cloud en fait partie.

Note: Le code sera disponible d’ici la fin de la semaine sur le SVN du DSB. Surement sous https://svn.petalslink.com/svnroot/trunk/research/commons/dsb/modules/dsb-kernel, je mettrais a jour l’article en fonction…

Archetypes Petals JBI


Je pense avoir déjà fait un article sur les archetypes Petals JBI qui permettent de créer les structures de base des projets Maven pour les composants JBI et leurs artefacts de configuration (les so-called SA et SU). En cherchant un archetype dans la liste (énorme) donnée par la commande ‘mvn archetype:generate‘, je suis tombé sur ces fameux archetypes Petals JBI :

La question : Comment sont ils arrivés là? Maven introspecte t-il les artefacts sur quelque repository ou une ame bienveillante les a ajouté au fichier de configuration du plugin archetype? J’opte plus pour la première réponse…

Le support de WS-notification* dans Petals ESB


Petals ESB

Image via Wikipedia

Je profite de passer un peu de temps à aider les collègues de l’équipe produit sur le sujet des notifications dans Petals ESB qui est assez récent dans la suite Petals pour proposer un article sur une vision de haut niveau du support des notifications dans le bus de service distribué.

L’architecture et l’intégration

Je ne reviens pas ici sur l’architecture de Petals ESB basée sur JBI (il y a assez d’articles la dessus sur mon blog) mais je voudrais parler de l’architecture choisie pour fournir un support aux notifications dans Petals. Malgré tout le support JBI est important ici car cette intégration est basée sur l’aspect composants JBI de Petals. Pour rappel, un composant JBI est une sorte de plugin qui vient enrichir le container JBI en offrant des fonctionnalités supplémentaires en tant que connecteur protocolaire ou de moteur service (les fameux Binding Components et Service Engines).
L’intégration des notifications est donc exclusivement basée sur des composants JBI via des composants dédiés d’une part et via une intégration dans le Kit de Développement de Composants (CDK) développé au sein du projet.

Du point de vue des spécifications, il est choisit de fournir une implémentation des spécifications WS-Notification de chez Oasis. Une vision simpliste de cette spécification fait intervenir un broker (un intermédiaire intelligent) pour gérer et découpler les émetteurs de notifications et les destinataires. C’est sur ce broker que les émetteurs s’enregistrent, et c’est aussi sur lui que les destinataires informent qu’ils sont intéressés par uu/des types de notifications précises. Pour plus de détails, je vous recommande de jeter un coup d’oeil à la spec elle même ou à Googler le sujet.

Du point de vue de l’intégration, le broker est implémenté dans un composant JBI dédié, le petals-se-notification. Comme tout le travail se passe généralement dans les autres composants JBI, le CDK (qui est le support pour le développement des composants) propose une activation du support des notifications en tant que producteur. Cette activation implique un enregistrement envers le broker dès son démarrage. Malgré cette activation, si aucun producteur n’est enregistré au niveau du broker, il ne se passera rien! En effet, l’architecture actuelle force les consommateurs de notifications à informer le broker de leur interêt pour des notifications via un système de topics. Je passe vite la dessus mais en gros, lorsque le consommateur s’enregistre au niveau du broker, le broker va relayer cette demande avec un contexte associé aux producteurs de notifications. Une fois cette étape achevée, des échanges de messages standard provoqueront potentiellement des notifications envoyées au broker qui fera ensuite son travail de relai.

Les principaux points forts de cette intégration sont :

  1. la possibilité d’utiliser ce médium de notifications pour tracer les échanges entre consommateurs et fournisseurs de services standards. Ces informations peuvent alors être remontées vers une console de BAM par exemple.
  2. L’utilisation du canal JBI pour échanger les notifications. Pas de nouveau canal de communication à créer, tout passe par les couches de communications du bus de service. Comme Petals est un bus de service nativement distribué, cette approche est vraiment un point important.
  3. Le support rapide via un CDK qui fournit toute la mécanique nécessaire pour implémenter ses producteurs et consommateurs de notifications.

Cette intégration a bien sûr des points faibles. Premièrement, il faut absolument que le composant qui fait acte de broker soit présent et robuste pour pouvoir gérer les notifications venant de N fournisseurs en tant que point central. Ensuite, ce broker doit (pour le moment) être unique dans le contexte du bus. En placer un autre sur un autre noeud du bus n’est pas possible actuellement (enfin si c’est possible mais des messages seront perdus).

La suite?

De nouveaux projets sont au programme en cette fin d’année avec pour but (un des buts plutôt) d’aller vers une architecture full EDA intégrée dans le coeur du bus. Cela va normalement supprimer les points négatifs cités précédemment avec notamment la suppression des composants JBI et le développement d’un broker distribué se basant sur l’architecture distribuée de Petals. Cela fera bien sûr de la matière pour les prochains articles de ce blog courant 2011.

En attendant, un prochain article portera surement sur quelque chose de plus technique avec un peu de code, je conseille de faire tourner la démo (disponible ici) qui met en oeuvre Petals ESB, Petals View et les notifications. Elle éclaircira mes dires, car le blahblah c’est bien, passer à l’action c’est mieux!

Créer sa couche de transport pour Petals ESB en 4 classes


Je profite d’avoir les doigts bien chauds (je viens de passer quelques jours à faire du M$ Word à plein temps, dure reprise après des vacances au grand air…) pour écrire un article que j’ai dans la tête depuis un petit moment : Comment développer sa propre couche de transport pour OW2-Petals ESB. Pour savoir ce qu’est la couche de transport dans Petals, allez jeter un coup d’oeil les précédents articles .

Note : Ce travail se base sur Petals ESB 3.0.2 mais est normalement compatible avec la v3.x. Tout le code est disponible sur le SVN du projet Petals ESB chez OW2 (le lien plus bas) et je ne l’ai pas inséré dans l’article car l’intérêt n’est pas de montrer que je sais coder en Java…

Le contexte

Petals ESB v3.x est livré avec une couche de transport permettant de faire communiquer les instances du bus de service basée sur une implémentation Java NIO. Le but de l’article est de présenter un framework de couche de transport et de montrer que développer une nouvelle couche en se basant sur le framework est simple et rapide.

Le framework

Le but n’est pas de détailler complètement le framework, mais juste les points d’extension qu’il offre. Le framework gère la logique d’envoi synchrone et asynchrone des messages, ce qu’il reste à implémenter est finalement juste la partie permettant de recevoir des messages (ie le serveur) et d’envoyer les messages sur le noeud distant (indépendamment de la logique Petals).

  • Le serveur: Il doit être capable de recevoir un message de la forme de son choix (tout dépend du protocole utilisé) et d’informer le framework qu’un nouveau message est recu après l’avoir converti en message Petals (ici JBI), rien de plus…
  • Le client: Doit pouvoir retrouver le serveur à appeler et lui envoyer le message après avoir transformé le message Petals (JBI) en message serveur-dépendant.

Le  framework est basé sur une abstraction de la couche de transport Java NIO de Petals ESB v3 et son code source est disponible dans ma sandbox dans les projets petals-transport-api et petals-transport.

Une implémentation Web service?

Oui parce que c’est la plus rapide et qu’elle est bien utile! Allez pour faire encore plus simple (et pour ne pas changer une équipe qui gagne), on va utiliser JAXWS & Apache CXF.

1. Le coté serveur

Il est en charge de démarrer le service de réception de messages, ici on va utiliser JAXWS pour exposer une instance de org.ow2.petals.transport.cxf.TransportServiceImpl qui implémente org.ow2.petals.esb.api.TransportService.

L’implémentation cré un message JBI depuis le message reçu par la pile Web service (via la méthode/opération #receive), et passe ce message au Receiver en appelant l’unique méthode #onMessage(MessageExchange). Le receiver n’est ici rien d’autre que le composant de transport du Framework (org.ow2.petals.transport.TransporterImpl dans le module petals-transport) qui implémente le service de transport de Petals ESB (org.ow2.petals.transport.Transporter) et qui possède l’intelligence pour faire remonter le message dans les couches de Petals ESB.

2. Le coté client

Ici aussi, rien de bien méchant. Il suffit de savoir créer un client Web service pour parler au serveur que l’on vient de présenter au point 1. Une fois encore, JAXWS et CXF font ca bien. Une factory est à implémenter (org.ow2.petals.transport.api.ClientFactory) et permet de créer des instance du client pour chaque container Petals ESB à invoquer.

3. What else?

Un peu de configuration via Fractal et le tour est joué. Une nouvelle couche de transport permet de faire communiquer les instances de Petals ESB via Web service au lieu de passer par NIO, tout cela avec quelques classes…

Et alors?

Avec quelques classes (même pas une dizaine, dans le meilleur des cas implémenter 4 interfaces doit être suffisant), on peut créer un nouveau type de transporter pour Petals ESB sans se soucier de :

  1. JBI. Ou presque la seule chose à faire est créer un message JAXWS depuis un message JBI et inversement (ca va il y a plus dur…)
  2. La logique de message synchrone et asynchrone. Tout cela est géré par le framework.
  3. La remontée du message vers le bon fournisseur de service.

On focalise ici vraiment sur la partie communication pure entre client et serveur. Pour valider le principe d’implémentation facile et rapide, j’ai créé un transporteur XMPP en à peu près un jour… Le code de ce transporteur XMPP n’est pas encore public mais ca ne devrait pas tarder. Il me faut juste un peu de temps…

Tout cela pour montrer qu’utiliser Petals ESB n’est pas limitant. L’architecture permet quand même des points d’extension intéressants, il faut juste s’y connaitre un peu (beaucoup). C’est juste notre métier…