SOA et SCA: Le Projet Apache Tuscany
Le projet Tuscany a pour but de créer une infrastructure SOA.
Tuscany est basé sur les spécifications définis par l’”Open CSA”.
SCA (Service Component Architecture) définit un modèle simple à base de service permettant la construction , l’assemblage et le déployment de services (Existant et nouveau) et de façon indépendante des languages et technologies.
SDO (Service Data Object) fournit une interface pour manipuler les différentes formes de données, y compris des documents XML, qui peuvent exister dans un réseau de Services eet fournit les mécanismes pour des conversions.
Première Application Tuscany
Ce tutorial est inspiré (traduit ?) de getting started with tuscany
Etape 1 : Telecharger java, tuscany et maven
Téléchargement: “Tuscany Java SCA release“.
Construire le “Calulator” en java
Cet exemple illustre comment définir votre application en restant concentré sur la logique métier. Il vous ammene à travers les étapes de la construction d’un “Calculator”. Toutes les connections entre les “Components” à l’intérieur du “Composite” sont locales et décrires en utilisant des Interfaces Java.
Etape 0 - Obtenir les librairies nécessaires
Pour cela il faut utiliser maven.
voila le POM.xml:
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>0.0.0</modelVersion>
- <groupId>com.bg.soa.test</groupId>
- <artifactId>bg_soa_test_tutos_tuscany</artifactId>
- <packaging>jar</packaging>
- <version>1.0-SNAPSHOT</version>
- <name>bg_soa_test_tutos_tuscany</name>
- <url>http://maven.apache.org</url>
- <repositories>
- <repository>
- <id>apache.incubator</id>
- <url>http://people.apache.org/repo/m2-incubating-repository</url>
- </repository>
- </repositories>
- <dependencies>
- <dependency>
- <groupId>org.apache.tuscany.sca</groupId>
- <artifactId>tuscany-host-embedded</artifactId>
- <version>1.2-incubating</version>
- </dependency>
- <dependency>
- <groupId>org.apache.tuscany.sca</groupId>
- <artifactId>tuscany-implementation-java-runtime</artifactId>
- <version>1.2-incubating</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.tuscany.sca</groupId>
- <artifactId>tuscany-binding-ws-axis2</artifactId>
- <version>1.2-incubating</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.tuscany.sca</groupId>
- <artifactId>tuscany-host-tomcat</artifactId>
- <version>1.2-incubating</version>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- </dependencies>
- </project>
Si vous travaillé avec eclipse, placé ce fichier à la racine de votre projet, puis tapez:
- mvn eclipse:eclipse
Etape 1 - Définir quels sont les blocs nécessaires.
Réflechissez à comment votre application peut être divisé en petites fonctions et/ou services.Chaque bloc est une unité logique d’opération qui peut être utilisée dans une application englobante. Pour notre exemple, le “Calculator” sera divisé en 5 blocs: AddService bloc, SubstractService bloc, MultiplyService bloc, DivideService bloc et un bloc principal qui accepte des requètes et les route vers le service approprié.Nous appelerons ce bloc “CalculatorService”.
Etape 2 - Implémenter chaque bloc
Maintenat que vous avez identifié les blocs de fonctionnalité de votre application, vous ètes prét pour les créer.
En SCA chaque bloc de fonctionnalité est appelé un “Component”. Aussi regardons comment on implémente un “Component”.
Nous prendrons comme premier exemple le bloc - ou “Component” - AddService .
Le “Component” AddService fournira un service qui additionne 2 nombres l’un à l’autre.Le “Component” CalculatorService utilise le “Component” AddService à chaque fois qu’on lui demande de faire une addition.
Si nous devions écrire le “Component” AddService en Java classique, nous pourrions commencer par décrire une Interface Java.
- package com.bg.soa.tuscany.calculator;
- public interface AddService {
- double add(double n1, double n2);
- }
Maintenant , nous fournissons une implementation de cette interface.
- package com.bg.soa.tuscany.calculator;
- public class AddServiceImpl implements AddService {
- @Override
- public double add(double n1, double n2) {
- return n1+n2;
- }
- }
Mais Attend! On est en train d’écrire un “Component SCA” ? Ca doit être plus compliqué qu’une interface et son implementation, non ? Bon, en fait, un SCA “Component” peut être écrit en Java classique, c’est ce que nous avons fait.
Nous pouvons utiliser SCA pour exposer ce service que fournit le “Component” addService à d’autres acteurs, par exemple des Web-Services, JMS ou RMI, sans changer une ligne de code à l’implémentation de AddService.
Dans l’application finale, il aura aussi à appeler les “Component” SubstracService, MultiplyService et DivideService.
A nouveau, nous commencerons par définir une interface parceque CalculatoService doit lui-même fournir une interface que d’autres appelleront.
- package com.bg.soa.tuscany.calculator;
- public interface CalculatorService {
- double multiply(double n1, double n2);
- double add(double n1, double n2);
- double substract(double n1, double n2);
- double divide(double n1, double n2);
- }
Maintenant, nous implementons cette interface:
- package com.bg.soa.tuscany.calculator;
- import org.osoa.sca.annotations.Reference;
- public class CalculatorServiceImpl implements CalculatorService {
- private AddService addService;
- private SubtractService subtractService;
- private MultiplyService multiplyService;
- private DivideService divideService;
- public void setAddService(AddService addService) {
- this.addService = addService;
- }
- ... methodes set pour les autres attributs à rajouter
- public double add(double n1, double n2) {
- return addService.add(n1, n2);
- }
- ...implementation des autre méthodes définies dans l'interface ici.
- }
On aura remarqué l’annotation “@Reference”.
Nous avons maintenant quelques “Components” implémenté en Java.Chaque “Component” a une interface bien définie, utilisant java dans notre exemple.
Step 3 - Assembler l’application:
Tout est parfait, mais comment exécuter ces deux “Components”. Oui bien sûr, le programmeur java qui est en nous veut foncer, écrire les lignes permettant de connecter nos deux “Components” ensemble et de les éxecuter. On pourrait le faire facilement dans notre cas:
- public class CalculatorClient {
- CalculatorServiceImpl calculatorService = new CalculatorServiceImpl();
- AddService addService = new AddServiceImpl();
- calculatorService.setAddService(addService);
- //appeler les autres methodes ici, si nous avons implementé SubtractService, MultiplyService, DivideService
- }
- }
Mais cela n’utilise pas Tuscany SCA, et étendre ce code pour implementer un Web-Srvice par exemple ne serait pas simple.
En premier, changeons le code pour appeler le “Tuscany SCA runtime” avant d’appeler nos “Components”.
- package com.bg.soa.tuscany.calculator;
- import org.apache.tuscany.sca.host.embedded.SCADomain;
- public class MainApp {
- static boolean isOn =true;
- SCADomain scaDomain = SCADomain.newInstance("Calculator.composite");
- CalculatorService calculatorService = scaDomain.getService(CalculatorService.class, "CalculatorServiceComponent");
- }
- }
Vous pouvez voir que nous commençons par utiliser une méthode static pour obtenir une instance de SCADomain.
Le SCADomain est un concept en SCA qui represente les frontières d’un sysème SCA.
Il pourrait être distribué entre plusieurs processeurs.
Pour l’instant, regardons comment cela fonctionne à l’intérieur d’une seule JVM.
Voilà le XML à l’intérieur de ce fichier “Calculator.composite” qui est dans le classpath.
la dernière ligne est là pour empécher la JVM de s’arrêter. Nous verrons plus loin (Quand nos exposerons des WS par exemple) à quoi cela servira.
- <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" name="Calculator">
- <component name="CalculatorServiceComponent">
- <implementation.java class="com.bg.soa.tuscany.calculator.CalculatorServiceImpl"/>
- <reference name="addService" target="AddServiceComponent" />
- <!-- references a SubtractComponent, MultiplyComponent et DivideComponent -->
- </component>
- <component name="AddServiceComponent">
- <implementation.java class="com.bg.soa.tuscany.calculator.AddServiceImpl"/>
- </component>
- <!-- definitions de SubtractComponent, MultiplyComponent et DivideComponent -->
- </composite>
Vous pouvez observer que nous avons défini 2 “components” et spécifié les classes Java implémentant ces “components” que Tuscany SCA a besoin de charger.
Ce sont les classes que nous avons juste implémentées.
Dans le XML, cette référence correspond au “AddServiceComponent”.
Ce n’est pas une coincidence que le nom de la référence “addService” corresponde au nom du champs addService que nous avons créé quand nous avons implémenté “CalculatorServiceImpl”.
Le moteur “Tuscany SCA” parse les informations du fichier XML et les utilise pour construire les objets et leurs relations qui représente notre application “Calculator”.
Il crée en premiet des instances de AddServiceImpl et CalculatorServiceImpl.
Il injecte ensuite une référence de l’objet AddServiceImpl dans le champs addService de l’objet CalculatorServiceImpl.
Si vous regardez à nouveau comment nous avons implémenté le CalculatorService, vous remarquerez une annotation @Reference qui dit à SCA quel champs sont à référencé.
C’est equivalent à ce bout de code pour un clent java habituel:
- CalculatorServiceImpl calculatorService = new CalculatorServiceImpl();
- AddService addService = new AddServiceImpl();
- calculatorService.setAddService(addService);
Une fois que le fichier composite est chargé dans le SCADomain, notre client demande au SCADomain de nous donner une référence vers le component appelé “CalculatorServiceComponent”.
- CalculatorService calculatorService = scaDomain.getService(CalculatorService.class, "CalculatorServiceComponent");
Nous pouvons utiliser cette référence pour accéder aux méthodes que nous avons créées, ici par exemple, la méthode CalculatorServiceImpl.add().
Les spécifications SCA décrive souvent les applications SCA sous forme de diagramme.Cela aide souvent quels sont les components qui composent une application et comment ils sont cablés ensemble.
Si nous traçons un diagramme de ce que nous avons construit dans notre exemple, nous obtenons quelquechose comme la figure suivante:
Step 4 - Déployer l’application:
Si le fichier “Calculator.composite” est dans notre class-path, ainsi que les autres librairies (les .jar), nous pouvons éxécuter notre exemple.
Nous proposons ici un exemple de fichier ant permettant la compilation et l’execution.
Il faut bien sûr adapter les properties tuscanyHome …
On peut remarquer que la liste des librairies (des jar) est définie dans le manifest du tuscany-sca-manifest.jar . Ce jar est livré uniquement avec le binaire de tuscany (Pas avec les sources).
- <project name="sample-calculator-webapp" default="compile">
- <property name="tuscanyHome" location="C:\java\tuscany-sca-1.2-incubating" />
- <property name="test.class" value="com.bg.soa.tuscany.calculator.MainApp" />
- <property name="test.jar" value="bg-sample-calculator.jar" />
- <target name="init">
- <mkdir dir="target/classes" />
- <mkdir dir="src/main/resources" />
- </target>
- <target name="compile" depends="init">
- <javac srcdir="src/main/java" destdir="target/classes" debug="on" source="1.5" target="1.5">
- <classpath>
- <pathelement location="${tuscanyHome}/lib/tuscany-sca-manifest.jar" />
- </classpath>
- </javac>
- <copy todir="target/classes">
- <fileset dir="src/main/resources" />
- </copy>
- <jar destfile="target/${test.jar}" basedir="target/classes">
- <manifest>
- <attribute name="Main-Class" value="${test.class}" />
- </manifest>
- </jar>
- </target>
- <target name="run-classes">
- <java classname="${test.class}" fork="true">
- <classpath>
- <pathelement path="target/classes" />
- <pathelement location="${tuscanyHome}/lib/tuscany-sca-manifest.jar" />
- </classpath>
- </java>
- </target>
- <target name="run">
- <java classname="${test.class}" fork="true">
- <classpath>
- <pathelement path="target/${test.jar}" />
- <pathelement location="${tuscanyHome}/lib/tuscany-sca-manifest.jar" />
- </classpath>
- </java>
- </target>
- <target name="clean">
- <delete quiet="true" includeemptydirs="true">
- <fileset dir="target" />
- </delete>
- </target>
- </project>
Utiliser d’autres configurations
En regardant en arrière, l’application “Calculator” construite en utilisant le “Tuscany SCA” n’est rien de plus qu’une application java ordinaire.
Cependant, nous avons un fichier xml “Composite” qui décrit comment notre application est assemblée.
C’est ce que nous cherchons depuis le début.Comme nous avons un fichier XML qui décrit notre application, cela devient facile avec “Tuscany SCA”.
Ce qui suit devrait faire l’affaire:
- <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" name="Calculator">
- <service name="CalculatorService" promote="CalculatorServiceComponent">
- <interface.java interface="com.bg.soa.tuscany.calculator.CalculatorService"/>
- <binding.ws uri="http://localhost:8181/CalculatorService"/>
antoine.guiral.info
bertrand.guiral.info
ertrand Guiral : formateur et consultant

