Librairie cliente pour Petals ESB


Avoir un Bus de services basé sur la spécification JBI c’est bien. Pouvoir le manager avec l’API JMX qui est définie dans le spécification c’est aussi pas mal, mais pouvoir le manager un utilisant des protocoles un peu plus ‘Internet-friendly’ et avec une librairie Java c’est encore mieux. Dans cet article, je vais présenter rapidement comment utiliser la librairie cliente qui est disponible depuis que Petals ESB fournit une API Web service ie depuis la version 3.0.

Le cas d’usage

Petals ESB est pleinement basé sur JBI est ne fournit pas forcément une API permettant d’exposer des services simplement. On pourrait imaginer avoir une API de management du style ‘bind(wsdlURI)’ où wsdlURI est l’URI du WSDL du service à lier au bus. La distribution de base ne fournissant pas ce genre d’API, il faut contourner cette lacune par l’utilisation de JBI et des APIs de management à distance.

La pratique et le code

Je passe sur la génération de Service Units et de Service Assemblies (des articles sont disponibles sur mon blog pur le faire avec des librairies Java ou avec le Petals Studio). Imaginons que nous ayons généré tout les artifacts JBI nécessaires coté client et que tous les composants JBI sont déjà installés sur le Bus. Comment soumettre ma SA au bus, et comment gérer son cycle de vie à distance?


package net.chamerling.blog.petalsclient;

import java.io.File;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;

import org.ow2.petals.kernel.ws.api.DeploymentService;
import org.ow2.petals.kernel.ws.api.PEtALSWebServiceException;
import org.ow2.petals.kernel.ws.api.to.AttachmentDescriptor;
import org.ow2.petals.kernel.ws.client.PetalsClient;
import org.ow2.petals.kernel.ws.client.PetalsClientFactory;

/**
 * Sample which is using the petals-kernel-wsclient library
 *
 * @author chamerling
 *
 */
public class App {

	public static void main(String[] args) {

		try {
			// get a client
			PetalsClient client = PetalsClientFactory.getInstance().getClient(
					"http://localhost:7600/petals/ws", 20000);

			// 'upload' the SA in the artifact repository
			File saFile = new File("sa.zip");
			AttachmentDescriptor ds = new AttachmentDescriptor();
			ds.setAttachment(new DataHandler(new FileDataSource(saFile)));
			client.getArtifactRepositoryService().addArtifact(ds);

			// Deploy the SA and start it
			String saId = "my-sa-id";
			DeploymentService dClient = client.getDeploymentService();
			dClient.deploy(saId);
			dClient.start(saId);

		} catch (PEtALSWebServiceException e) {
			e.printStackTrace();
		}
	}
}

Tout est dans le code :

  1. La SA est déposée dans le répertoire géré par le service d’artifact (par défaut, sous PETALS_HOME/artifacts/)
  2. La SA est déployée depuis le répertoire cité en 1
  3. La SA est démarrée.

Le code de l’exemple est disponible dans mon projet googlecode sous http://code.google.com/p/chamerling/source/browse/trunk/blog/petals-ws-client

L’acheminement de messages dans Petals ESB : #2 Le routage


Intro

Dans l’article précédent sur l’acheminement de messages dans Petals ESB, j’introduisais les notions, aujourd’hui nous allons regarder en détails la couche de routage du bus. Cette couche est largement appelée Router par les développeurs du Bus, et le sera donc dans cette article et dans la suite de la série.

L’archi simplifiée

L’architecture du Router utilise la notion très répandue et  fort utile de modules ie le Router invoque séquentiellement une liste de modules pour élire les services à appeller. A la fin de la traversée on se retrouve avec toutes les informations nécessaires pour appeler les services. On peut modifier cette liste en ajoutant ou supprimant des modules par configuration. Un schéma simplifié donne un Router avec cette tête :

Plus de détails sur l’utilisation des modules dans Petals et leur injection dans un vieil article (à non pas si vieux…).

L’implémentation

L’implémentation de base de Petals ESB est composée de 2 modules en émission :

  1. Le module qui interroge le registre de services et retourne une liste de point d’accès (endpoint dans le jargon service) en fonction des informations contenues dans le message d’entrée.
  2. Le module de résolution de la couche de transport. En fonction de la localisation des endpoints trouvés par le module précédent, un contexte est créé pour définir la couche de transport à utiliser (cette couche de transport sera détaillée dans le prochain article de la série).

On peut imaginer un grand nombre d’utilisations de ces modules. Personnellement, je les utilise à outrance par exemple pour :

  • Ajouter des informations de timestamp sur les messages
  • Notifier une couche de monitoring que des messages sont échangés entre consommateurs et fournisseurs de service
  • Logger les appels
  • Mettre à jour le choix de la couche de transport avec ma propre implémentation du transport de messages inter container

Outro

Vous en savez un peu plus sur le routage dans le bus de service Petals. il faut vraiment retenir que cette couche est vraiment extensible et customisable sans grand effort, en effet pas besoin de recompiler le coeur de Petals pour ajouter des fonctionnalités pour la résolution des endpoints. Dans le prochain article de la série, nous regarderons de plus prêt comment sont échangés les messages entre les instances de Petals.

L’acheminement de messages dans Petals ESB : #1 L’intro


L’intro

Je commence ici une petite série d’articles sur l’acheminement  de messages dans Petals ESB pour décrire d’abord simplement et par la suite plus techniquement (avec du code ) comment le message se balade dans le bus de services lors de l’invocation de services. Cette invocation passe par plusieurs étapes, qui sont ‘customisables’ et extensibles facilement pour répondre à des besoins distincts, on verra cette partie plus tard…

Le blahblah

On le dit depuis la première version de Petals ESB, Petals est Le bus de services distribué qui implémente la spécification JBI. Ici distribué signifie que des instances du bus de service sont lancées sur des hotes distincts et que du point de vue de l’utilisateur, cela est totalement transparent ie l’utilisateur n’a rien à configurer de plus qu’un fichier de description du réseau (contrairement aux concurrents où l’on doit généralement configurer des composants JBI pour exposer des services). On ne se place pas ici à un transport de messages au niveau applicatif mais vraiment à un niveau (abstrait) de transport. Pour être plus clair, l’architecture de Petals ESB est divisée en couches et pour faire simple on a :

  1. Le canal de communication. Le canal de communication est la couche d’accès utilisée au niveau des composants JBI et donc au niveau des consommateurs et fournisseurs de services. Lors de l’invocation d’un service, le composant qui invoque un service envoi un message au canal. Le canal possède aussi tout un jeu de ‘listeners’ qui permettent de recevoir des messages de la couche de niveau N-1 (ie la couche de routage) en mode fournisseur de services.
  2. La couche de routage. En mode consommateur de service, cette couche reçoit le message du canal de communication et est chargé de trouver le point d’accès (endpoint) à qui le message doit être envoyé. Cet endpoint peut être local ou distant (sur un autre instance de Petals ESB). Elle permet aussi une remontée du message vers le bon canal de communication et donc vers le bon fournisseur de service en mode fournisseur.
  3. La couche de transport. Cette couche reçoit le message et le endpoint auquel le message doit être envoyé. Elle envoi ce message au endpoint, qu’il soit local ou distant. La couche de transport gère bien sûr la réception des messages envoyés depuis les instances distantes pour l’invocation des services qui se trouvent sur l’instance locale.

La suite

Dans les prochains articles, je détaillerais les couches de routage et de transport, leurs features, leurs points d’extensions, etc, etc… Et avec peu de code, on verra que l’on peut customizer Petals ESB.

Mapping WSDL JBI


Cet article fait suite à une question récurrente des utilisateurs de Petals ESB : « Pourquoi j’ai une erreur au déploiement de mon service??? ». Je vais ici tenter de donner une réponse partielle à cette question car il peut y avoir beaucoup de raisons à une erreur de déploiement. La plus courante venant souvent de la configuration. Rien que bien technique ni compliqué dans cet article, juste un mini tutoriel pour mieux comprendre la philosophie Petals – JBI.

La spécification JBI est basée sur l’état de l’art des Web services et donc utilise WSDL pour la description des services ‘hostés’ ou liés à l’implémentation JBI. Petals ESB implémente (et étend – mais ça sera peut être l’objet d’un autre article sur le pourquoi du comment…) la spécification JBI depuis sa première version. Petals ESB est même certifié compatible JBI par SUN (RIP) après le passage du TCK JBI (Outil de test de compatibilité fournit par SUN). Bref, là n’est pas la question… Les descripteurs JBI servent à beaucoup de choses dans une implémentation JBI mais nous allons particulièrement regarder comment nous nous en servons dans l’exposition de services.

Un service exposé dans le bus fournit donc sa description via un WSDL associé. Ce service est activé dans le bus après le déploiement de ce que l’on appelle communément une ‘SA’ (Service Assembly) qui contient des ‘SU’ (Service Unit). Pour exposer un service dans le bus afin qu’il soit accessible à tout les consommateurs, la SU doit être en mode ‘provide’ ie fournisseur. Elle doit aussi définir le Endpoint, le Service et l’Interface qu’elle veut exposer. Prenons l’exemple du bon vieux service HelloWorld définit par le WSDL suivant :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:definitions name="HelloServiceImplService" targetNamespace="http://sample.petals.ow.org/" xmlns:ns2="http://schemas.xmlsoap.org/wsdl/" xmlns:ns3="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:ns9="http://www.w3.org/ns/wsdl/http" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns5="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:ns6="http://schemas.xmlsoap.org/wsdl/http/"
	xmlns:ns10="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:ns7="http://www.w3.org/ns/wsdl" xmlns:ns8="http://www.w3.org/ns/wsdl/soap">
	<ns2:types>
		<xs:schema elementFormDefault="unqualified" attributeFormDefault="unqualified" targetNamespace="http://sample.petals.ow.org/">
			<xs:element name="sayHello" type="tns:sayHello" xmlns:tns="http://sample.petals.ow.org/" />
			<xs:element name="sayHelloResponse" type="tns:sayHelloResponse" xmlns:tns="http://sample.petals.ow.org/" />
			<xs:complexType name="sayHello">
				<xs:sequence>
					<xs:element name="arg0" minOccurs="0" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="sayHelloResponse">
				<xs:sequence>
					<xs:element name="return" minOccurs="0" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
		</xs:schema>
	</ns2:types>
	<ns2:message name="sayHelloResponse">
		<ns2:part element="tns:sayHelloResponse" name="parameters" xmlns:tns="http://sample.petals.ow.org/" />
	</ns2:message>
	<ns2:message name="sayHello">
		<ns2:part element="tns:sayHello" name="parameters" xmlns:tns="http://sample.petals.ow.org/" />
	</ns2:message>
	<ns2:portType name="HelloService">
		<ns2:operation name="sayHello">
			<ns2:input message="tns:sayHello" name="sayHello" xmlns:tns="http://sample.petals.ow.org/" />
			<ns2:output message="tns:sayHelloResponse" name="sayHelloResponse" xmlns:tns="http://sample.petals.ow.org/" />
		</ns2:operation>
	</ns2:portType>
	<ns2:binding type="tns:HelloService" name="HelloServiceImplServiceSoapBinding" xmlns:tns="http://sample.petals.ow.org/">
		<ns3:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
		<ns2:operation name="sayHello">
			<ns3:operation style="document" soapAction="" />
			<ns2:input name="sayHello">
				<ns3:body use="literal" />
			</ns2:input>
			<ns2:output name="sayHelloResponse">
				<ns3:body use="literal" />
			</ns2:output>
		</ns2:operation>
	</ns2:binding>
	<ns2:service name="HelloServiceImplService">
		<ns2:port binding="tns:HelloServiceImplServiceSoapBinding" name="HelloServiceImplPort" xmlns:tns="http://sample.petals.ow.org/">
			<ns3:address location="http://localhost:9999/sample/HelloService" />
		</ns2:port>
	</ns2:service>
</ns2:definitions>
<pre>

Son descripteur JBI associé sera donc (lié a Petals via le composant Web service dans cet exemple) :

<?xml version="1.0" encoding="UTF-8"?>
<jbi:jbi version="1.0"
        xmlns:generatedNs="http://sample.petals.ow.org/"
        xmlns:jbi="http://java.sun.com/xml/ns/jbi"
	xmlns:petalsCDK="http://petals.ow2.org/components/extensions/version-5"
	xmlns:soap="http://petals.ow2.org/components/soap/version-4"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<jbi:services binding-component="true">
		<jbi:provides interface-name="generatedNs:HelloService"
			service-name="generatedNs:HelloServiceImplService"
			endpoint-name="HelloServiceImplPort">

			<!-- CDK specific elements -->
			<petalsCDK:timeout>60000</petalsCDK:timeout>
			<petalsCDK:wsdl>Service.wsdl</petalsCDK:wsdl>

			<!-- Component specific elements -->
			<soap:address>http://localhost:9999/sample/HelloService</soap:address>
			<soap:soap-version>11</soap:soap-version>
			<soap:add-root>false</soap:add-root>
			<soap:chunked-mode>false</soap:chunked-mode>
			<soap:cleanup-transport>true</soap:cleanup-transport>
			<soap:mode>SOAP</soap:mode>
		</jbi:provides>
	</jbi:services>
</jbi:jbi>

Où on respecte bien que :

  1. JBI ‘endpoint-name‘ = Valeur de l’attribut ‘name’ du Port dans le WSDL
  2. JBI ‘service-name‘ = Valeur de l’attribut ‘name’ du Service dans le WSDL (avec JBI Service NameSpace = targetNamespace du WSDL)
  3. JBI ‘interface-name‘ = Valeur de l’attribut ‘name’ du PortType dans le WSDL (avec JBI Interface NameSpace = targetNamespace du WSDL)

Petals ESB v3.x ne vous insultera plus lors du déploiement de vos services. Une solution simple pour ne pas se faire insulter, est d’utiliser le Studio Petals qui facilite grandement la vie des développeurs!