WOW !! MUCH LOVE ! SO WORLD PEACE !
Fond bitcoin pour l'amélioration du site: 1memzGeKS7CB3ECNkzSn2qHwxU6NZoJ8o
  Dogecoin (tips/pourboires): DCLoo9Dd4qECqpMLurdgGnaoqbftj16Nvp


Home | Publier un mémoire | Une page au hasard

 > 

Architecture soa (architecture orientée services)

( Télécharger le fichier original )
par Virginie ELIAS
CNAM Nantes - Pays de la Loire - Ingénieur en Informatique 2009
  

précédent sommaire suivant

Bitcoin is a swarm of cyber hornets serving the goddess of wisdom, feeding on the fire of truth, exponentially growing ever smarter, faster, and stronger behind a wall of encrypted energy
Exemples de grandeurs mesurables et unités associées

Grandeur mesurée

Unité d'expression

Symbole

Nature ou rôle

Multiples utilisés

Longueur

mètre

m

 

mm, cm, km

Masse

kilogramme

Kg

 

g, q, t

Temps

Seconde

S

 

ms, mn, h

Superficie

mètre carré

M2

 

km², a, ha

Température

Kelvin

K

 

°C, °F

Volume

mètre cube

M3

 

mm3, cm3, l, hl

Taux

Pourcentage

%

 

°/°°

Package Oracle : Extraction

PROCEDURE Demande_Extraction

(

P$Table in Varchar2, -- Table a extraire

P$Fichier in Varchar2, -- Fichier de sortie

P$Repertoire in Varchar2, -- Répertoire de sortie

P$Separateur in Varchar2 Default ',', -- Séparateut Csv

P$Entetes in Varchar2 Default 'O', -- Entete des colonnes

P$Date in Varchar2 Default 'DD/MM/YYYY', -- Format date

P$Where in Varchar2 Default Null, -- Clause Where

P$Order in Varchar2 Default Null -- Clause Order by

) IS

F$Fichier UTL_FILE.FILE_TYPE ;

L$Ligne Varchar2(32767) ;

L$I Integer ;

L$Date Varchar2(40) := '''' || P$Date || '''' ;

XmlFic Utl_File.File_Type;

XmlData CLOB;

Fin BOOLEAN := TRUE;

qryCtx DBMS_XMLGEN.ctxHandle;

TYPE REFCUR1 IS REF CURSOR ;

cur REFCUR1;

-- Colonnes de la table --

CURSOR C_COLTAB ( P$Tab IN VARCHAR2 ) IS

SELECT

COLUMN_NAME,

DATA_TYPE

FROM

USER_TAB_COLUMNS

WHERE

TABLE_NAME = P$Tab

AND

DATA_TYPE IN ('CHAR','VARCHAR2','NUMBER','DATE','FLOAT')

;

L$Separateur Varchar2(2) := P$Separateur ;

L$Requete Varchar2(10000) ;

L$Desc Varchar2(10000) ;

L$SQLW VARCHAR2(10000):= 'SELECT ';

L$Col VARCHAR2(256);

-----------------------------------------

-- Ouverture d'un fichier d'extraction --

-----------------------------------------

FUNCTION Ouvrir_fichier

(

P$Dir in Varchar2,

P$Nom_Fichier in Varchar2

) RETURN UTL_FILE.FILE_TYPE

IS

Fichier UTL_FILE.FILE_TYPE ;

L$Msg Varchar2(256);

Begin

Fichier := UTL_FILE.FOPEN( P$Dir, P$Nom_Fichier, 'W', 32764 ) ;

If not UTL_FILE.IS_OPEN( Fichier ) Then

L$Msg := 'Erreur ouverture du fichier (' || P$Dir || ') ' || P$Nom_Fichier ;

RAISE_APPLICATION_ERROR( -20100, L$Msg ) ;

End if ;

Return( Fichier ) ;

Exception

When UTL_FILE.INVALID_PATH Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'File location is invalid.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.INVALID_MODE Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'The open_mode parameter in FOPEN is invalid.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.INVALID_FILEHANDLE Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'File handle is invalid.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.INVALID_OPERATION Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'File could not be opened or operated on as requested.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.READ_ERROR Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'Operating system error occurred during the read operation.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.WRITE_ERROR Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'Operating system error occurred during the write operation.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.INTERNAL_ERROR then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'Unspecified PL/SQL error';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.CHARSETMISMATCH Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'A file is opened using FOPEN_NCHAR,'

|| ' but later I/O operations use nonchar functions such as PUTF or GET_LINE.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.FILE_OPEN Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'The requested operation failed because the file is open.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.INVALID_MAXLINESIZE Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'The MAX_LINESIZE value for FOPEN() is invalid;'

|| ' it should be within the range 1 to 32767.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.INVALID_FILENAME Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'The filename parameter is invalid.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.ACCESS_DENIED Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'Permission to access to the file location is denied.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.INVALID_OFFSET Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'The ABSOLUTE_OFFSET parameter for FSEEK() is invalid;'

||' it should be greater than 0 and less than the total number of bytes in the file.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.DELETE_FAILED Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'The requested file delete operation failed.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When UTL_FILE.RENAME_FAILED Then

L$Msg := P$Dir || P$Nom_Fichier || ' : ' || 'The requested file rename operation failed.';

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

When others Then

L$Msg := 'Erreur : ' || To_char( SQLCODE ) || ' sur ouverture du fichier ('

|| P$Dir || ') ' || P$Nom_Fichier ;

RAISE_APPLICATION_ERROR( -20070, L$Msg ) ;

End Ouvrir_fichier ;

Begin

-- Ouverture du fichier --

F$Fichier := Ouvrir_fichier( P$Repertoire, P$Fichier||'.txt' ) ;

-- Affichage des entetes de colonne ? --

If Upper(P$Entetes) = 'O' Then

L$I := 1 ;

For COLS IN C_COLTAB( P$Table ) Loop

If L$I = 1 Then

L$Ligne := L$Ligne || COLS.COLUMN_NAME ;

Else

L$Ligne := L$Ligne || L$Separateur || COLS.COLUMN_NAME ;

End if ;

L$I := L$I + 1 ;

End loop ;

-- Ecriture ligne entetes --

UTL_FILE.PUT_LINE( F$Fichier, L$Ligne ) ;

ElsIf Upper(P$Entetes) = 'I' Then

L$Separateur := ',' ;

L$Desc := 'INSERT INTO ' || P$Table || ' (' ;

L$I := 1 ;

For COLS IN C_COLTAB( P$Table ) Loop

If L$I = 1 Then

L$Desc := L$Desc || COLS.COLUMN_NAME ;

Else

L$Desc := L$Desc || L$Separateur || COLS.COLUMN_NAME ;

End if ;

L$I := L$I + 1 ;

End loop ;

L$Desc := L$Desc || ' ) VALUES (' ;

End if ;

-- Réenvoyer un résultat lisible d'un browser dans le cas où l'invocation est faite par HTTP

htp.htmlopen;htp.bodyopen;htp.line;

htp.tableopen('border');

htp.tablecaption(P$Table,'center');

htp.tablerowopen;

--

htp.tableheader(L$Ligne);

----

-- Génération de la requete --

L$I := 1 ;

FOR COLS IN C_COLTAB( P$Table ) LOOP

IF L$I > 1 THEN

L$SQLW := L$SQLW || '||' ;

END IF ;

If COLS.DATA_TYPE IN ('NUMBER','FLOAT') Then

L$Col := 'Decode(' || COLS.COLUMN_NAME || ',NULL, ''NULL'',To_char("'

|| COLS.COLUMN_NAME || '"))' ;

ElsIf COLS.DATA_TYPE = 'DATE' Then

If Upper(P$Entetes) = 'I' Then

L$Col := 'Decode(' || COLS.COLUMN_NAME || ',NULL,''NULL'',''to_date(''''''||'

|| 'To_char("' || COLS.COLUMN_NAME || '",'|| L$Date ||')' || '||'''''','''|| L$Date||''')'')' ;

Else

L$Col := 'To_char("'|| COLS.COLUMN_NAME || '",'|| L$Date ||')' ;

End if ;

Else

If Upper(P$Entetes) = 'I' Then

L$Col := 'Decode(' || COLS.COLUMN_NAME || ',NULL, ''NULL'',' || ''''''''''

|| '|| REPLACE("'|| COLS.COLUMN_NAME || '",CHR(39),CHR(39)||CHR(39))' || '||' || ''''''''')' ;

Else

L$Col := '"'|| COLS.COLUMN_NAME || '"' ;

End if ;

End if ;

IF L$I = 1 THEN

L$SQLW := L$SQLW || L$Col ;

ELSE

L$SQLW := L$SQLW || '''' || L$Separateur || '''' || '||' || L$Col ;

END IF ;

L$I := L$I + 1 ;

END LOOP ;

L$Requete := L$SQLW || ' FROM ' || P$Table ;

If P$Where is not null Then

-- ajout de la clause WHERE --

L$Requete := L$Requete || ' WHERE ' || P$Where ;

End if ;

If P$Order is not null Then

-- ajout de la clause ORDER BY --

L$Requete := L$Requete || ' ORDER BY ' || P$Order ;

End if ;

--F_TRACE( L$Requete, 'T' ) ;

htp.tableRowClose;

htp.tablerowopen;

-- Extraction des lignes --

Open cur For L$Requete ;

Loop

Fetch cur Into L$Ligne ;

Exit when cur%NOTFOUND ;

--

htp.tablerowopen;

htp.tabledata(L$Ligne);

htp.tablerowclose;

--

-- Ecriture du fichier de sortie --

If Upper(P$Entetes) = 'I' Then

UTL_FILE.PUT_LINE( F$Fichier, L$Desc || L$Ligne || ' );' ) ;

Else

UTL_FILE.PUT_LINE( F$Fichier, L$Ligne ) ;

End if ;

End loop ;

--

htp.tablerowclose;

htp.tableclose;

htp.bodyclose;

htp.htmlclose;

--

Close cur ;

-- Fermeture fichier --

UTL_FILE.FCLOSE( F$Fichier ) ;

if P$Where is null

then

qryCtx := dbms_xmlgen.newContext ('select * FROM '|| P$Table || '');

else

qryCtx := dbms_xmlgen.newContext ('select * FROM '|| P$Table || ' where ' || P$Where || '');

end if;

DBMS_XMLGEN.setRowsettag(qryCtx, '');

DBMS_XMLGEN.setRowTag(qryCtx, P$Table);

DBMS_XMLGEN.setMaxRows(qryCtx, 1);

-- Créer des données au format XML à partir d'une requête :

XmlData :=DBMS_XMLGEN.getXML(qryCtx);

-- Copie les données au format XML dans un fichier :

XmlFic := sys.Utl_File.FOpen (P$Repertoire, P$Table||'.xml', 'W');

WHILE FIN LOOP

-- Assigner le XML Schema

xmldata := REPLACE(Xmldata,'<'||P$Table||'>',

'<'||P$Table||'_PIVOT:'||P$Table||' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:'||P$Table||'_PIVOT="http://xml.netbeans.org/schema/'||P$Table||'"

xsi:schemaLocation="http://xml.netbeans.org/schema/'||P$Table||' '||P$Table||'.xsd">');

xmldata := REPLACE(Xmldata,'</'||P$Table||'>','</'||P$Table||'_PIVOT:'||P$Table||'>');

Utl_File.Put (XmlFic, SUBSTR (XmlData,1,32767));

Utl_File.FFlush(XmlFic);

IF LENGTH (XmlData) > 32767 THEN

XmlData := SUBSTR (XmlData, 32768);

ELSE

FIN := FALSE;

DBMS_OUTPUT.PUT_LINE ('FIN');

END IF;

END LOOP;

Utl_File.FClose (XmlFic);

Illustration de la flexibilité apportée par le concept de service

Pseudo Code L3G :

Début de saisie d'un devis pour un tiers (client, produit, quantite, date_livraison)

select * from Client where nomduClient='client'

Si Client n'existe pas

Alors

Saisir information du client

insert into Client... values...

Fin

select * from Produit where nomduProduit = `produit'

Si Produit.quantitestock - quantite_reservee < quantite

Alors

select Produit.delais from Produit where nomduProduit = `produit'

si Date_jour + Produit.delais > date_livraison

Alors

Message «Devis refusé car stock indisponible dans délais imparti»

Exit

Fin

Fin

Update produit set quantite_reservee = quantite_reservee + quantite

Insert into devis ... values ...

Fin de Saisie de devis

Constats :

Constat :

q Mélange des genres : Client, Produit, Devis,

q Appel aux bases de données de façon séquentielle,

q Logique monolithique,

q Pas de couplage faible car tout est lié,

q Rien n'est réutilisable ni exposable,

q Aucune logique de processus,

q Les règles d'enchaînement sont noyées dans le code.

Pseudo Code d'appel de services :

Début de saisie d'un devis pour un tiers (client, produit, quantite, date_livraison)

Client = ObtenirleClient(client)

Si AnalyserStockProduit(produit, quantite) = rupture_stock

Alors

Si AnalyserDelaisProduit(produit,date_livraison) = date_impossible

Alors

Message «Devis refusé car stock indisponible dans délais imparti»

Exit

Fin

Fin

MettreajourStockreserve(produit, quantite)

CreerleDevis(Client, produit, quantite,date_livraison)

Fin de Saisie de devis

Constats :

q Appels de 5services faiblement couplés

q Code clair

q Services réutilisables par d'autres programmes. Il est facile d'imaginer l'appel des deux services :

MettreajourStockreserve(produit, quantite) lors de la livraison du produit, ObtenirleClient(client) dans le cas d'une saisie de commande sans devis préalable.

Annuaire de Services :

Début ObtenirleClient(client)

select * from Client where nomduClient=client

Si n'existe pas

Alors

Saisir information du client

insert into Client... values...

Fin

Retourner Client

Fin ObtenirleClient

Début CreerleDevis(Client, produit, quantite, date_livraison)

insert into Devis... values...

Fin CreerleDevis

Début AnalyserStockProduit(produit,quantite)

select quantitestock + quantite_reservee from Produit

where nomduProduit = produit

Si quantitestock + quantite_reservee < quantite Alors

Retourne rupture_stock

Sinon

Retourne ok

Fin

Fin AnalyseStockProduit

Début AnalyserDelaisProduit(produit,date_livraison)

select delais Produit where nomduProduit = produit

Si date_jour + delais < date_livraison Alors

Retourne date_impossible

Sinon

Retourne ok

Fin

Fin AnalyseDelaisProduit

Début MettreajourStockreserve(produit, quantite)

Update produit set quantite_reservee = quantite_reservee + quantite

Fin CreerleDevis

Illustration de l'interopérabilité (traduction d'une source IBM162(*))

1) Le diagramme de classe (outil Rose) ci dessous représente le processus d'approbation de prêt (demande de crédit, évaluation du risque, approbation, erreur) :

Illustration 146 : Classe sous Rose

2) Proposition IBM de diagramme d'activité :

Illustration 147 : la "Demande de Prêt"

Les activités sont nommées (exemple : invokeAssessor) via des rectangles aux coins arrondis. Les actions devant être exécutées selon des conditions d'entrée à l'activité se trouvent dans le cartouche de l'activité. Par exemple, riskAssessment (une variable) est mis à jour selon le résultat du service de contrôle. Les Acteurs sont représentés dans des cadres encapsulant les activités pour lesquelles un message de réception ou d'émission leur est attribué. Une activité sans cadre (sans Acteur) signifie quelle est gérée par le processus lui-même sans besoin de service particulier. Les flèches quant à elles, indiquent le sens du processus. Ici, l'activité « Reply » renvoie une réponse au client, achevant l'exécution du processus.

3) Un export XMI163(*) du diagramme d'activités est effectué :

Illustration 148 : Export XMI

4) Sous Eclipse, un projet Java est créé pour importer le fichier XMI. Puis la génération BPEL est déclenchée (fonction standard). Enfin, après avoir appuyé sur « Finish », un certain nombre de fichiers apparaissent dans le projet, dont les fichiers BPEL et WSDL (Service Web).

Profile Construct

Concepts BPEL4WS

<<process>> class

BPEL process definition

Activity graph on a <<process>> class

BPEL activity hierarchy

<<process>> class attributes

BPEL variables

Hierarchical structure and control flow

BPEL sequence and flow activities

<<receive>>, <<reply>>, <<invoke>> activities

BPEL activities

Tableau 11 : Mapping UML / BPEL

<process name="loanApprovalProcess" ...>

<variables>

<variable name="request"

messageType="loandef:creditInformationMessage"/>

<variable name="riskAssessment"

messageType="asns:riskAssessmentMessage"/>

...

</variables>

...

<flow>

<receive name="receive1" partner="customer"

portType="apns:loanApprovalPT"

operation="approve" variable="request"

createInstance="yes">

<source linkName="receive-to-assess"

transitionCondition=

"bpws:getVariableData('request', 'amount')<10000"/>

<source linkName="receive-to-approval"

transitionCondition=

"bpws:getVariableData('request', 'amount')>=10000"/>

</receive>

<invoke name="invokeAssessor" partner="assessor"

portType="asns:riskAssessmentPT"

operation="check"

inputVariable="request"

outputVariable="riskAssessment">

<target linkName="receive-to-assess"/>

<source linkName="assess-to-setMessage"

transitionCondition=

"bpws:getVariableData('riskAssessment', 'risk')='low'"/>

<source linkName="assess-to-approval"

transitionCondition=

"bpws:getVariableData('riskAssessment', 'risk')!='low'"/>

</invoke>

<assign name="assign">

<target linkName="assess-to-setMessage"/>

<source linkName="setMessage-to-reply"/>

<copy>

<from expression="'yes'"/>

<to variable="approvalInfo" part="accept"/>

</copy>

</assign>

...

<reply name="reply" partner="customer" portType="apns:loanApprovalPT"

operation="approve" variable="approvalInfo">

<target linkName="setMessage-to-reply"/>

<target linkName="approval-to-reply"/>

</reply>

</flow>

</process>

Illustration 149 : Extrait de la traduction BPEL

5) Enfin, pour tester le résultat, il faut déployer les fichiers générés via un serveur TOMCAT par exemple ou sous WebSphere Application Server.

Illustration 150 : Déploiement du Processus

Après avoir cliqué sur "Continue Deployment", insérer les fichiers requis pour les différents rôles. Dans cet exemple, il y en a deux : LoanAssessor and LoanApprover.

Illustration 151 : Déploiement des services

Une fois le Processus déployé, le lancer en invoquant le script LoanApprovalSample :

LoanApprovalSample [soap-address] first-name last-name amount.

Par exemple : LoanApprovalSample http://localhost:80/bpws4j/soaprpcrouter Joe Black 10

Structures : Tiers, RIB et Adresses

* 162 http://www.ibm.com/developerworks/webservices/library/ws-uml2bpel

* 163 XMI (XML Metadata Interchange) : définit un format d'échange standard entre ateliers logiciels.

précédent sommaire suivant






Bitcoin is a swarm of cyber hornets serving the goddess of wisdom, feeding on the fire of truth, exponentially growing ever smarter, faster, and stronger behind a wall of encrypted energy








"Nous devons apprendre à vivre ensemble comme des frères sinon nous allons mourir tous ensemble comme des idiots"   Martin Luther King