file di ESB

Transcript

file di ESB
Linee guida per lo sviluppo dei servizi applicativi in
ambiente CARTe
Versione 1.7
24/07/2010
1 Introduzione
...................................................... 3
2
Uso del Componente di Integrazione della Porta di Dominio............................................. 3
2.1 Modalità d'uso trasparente dei Servizi.............................................................................4
2.2 Uso del Servizio IntegrationManager................................................................................5
2.2.1 Invocazione di una porta delegata tramite Integration Manager...........................8
2.2.2 Accesso ai messaggi ricevuti tramite Integration Manager.....................................9
3
Contenuti delle Risposte Applicative................................................................................... 11
4
La gestione degli errori nell'Interazione tra Servizio Applicativo e Porta Delegata ......12
5
Aspetti di integrazione nei Profili Asincroni....................................................................... 17
6
Interscambio di Informazioni tra SIL e PdD...................................................................... 19
6.1 Integrazione tramite QUERY_STRING.........................................................................21
6.2 Integrazione tramite l’uso dell’Header SOAP eToscana...............................................22
7
uso del meccamismo dei Filtri JMS.....................................................................................25
7.1 Impostazione delle proprietà da parte del SIL Pubblicatore .......................................25
8
Proxy CART........................................................................................................................... 28
9
Mediatori TSB........................................................................................................................28
9.1 Il linguaggio di configurazione.........................................................................................29
9.2 Alcuni Esempi....................................................................................................................30
9.3 L'esempio delle Comunicazioni Obbligatorie.................................................................30
9.4 Utilizzo di Synapse per il TSB.........................................................................................31
Allegato A: Interfaccia WSDL del Servizio di IntegrationManager.........................................44
Allegato ’B’: Header SOAP eToscana......................................................................................... 68
Domande Frequenti....................................................................................................................... 71
1 Introduzione
Nella specifica SPCoop, un dominio è definito come il confine di responsabilità di un ente o
soggetto amministrativo e racchiude al suo interno tutte le applicazioni da esso gestite. Il confine
applicativo del Dominio è rappresentato dalla Porta di Dominio (PdD), attraverso la quale devono
transitare tutte le comunicazioni da e verso il dominio.
Le Porte di Dominio si parlano tra di loro scambiandosi richieste e risposte in un formato parte
della specifica SPCoop, denominato busta eGov. Tuttavia il formato della busta non è parlato
nativamente dalle applicazioni, pertanto la Porta di Dominio deve anche occuparsi di convertire le
richieste applicative nel formato busta eGov. Facendo riferimento a questa problematica, i compiti
della Porta di Dominio vengono solitamente classificati in due componenti: il componente di
cooperazione, che riguarda la comunicazione tra le Porte di Dominio e quello di integrazione, che
riguarda la comunicazione tra i Servizi Applicativi dell’Ente e la Porta di Dominio.
Il componente di integrazione si differenzia a sua volta in due diversi moduli: la porta delegata e la
porta applicativa. In particolare la porta delegata è utilizzata come proxy per l’accesso al servizio
destinazione, mentre la porta applicativa deve essere in grado di gestire la consegna dei contenuti
delle buste eGov ricevute al corrispondente servizio applicativo interno al dominio destinazione.
Differentemente da quanto avviene per il componente di cooperazione (busta eGov), per il
componente di integrazione la specifica SPCoop si limita a presentare un esempio di massima di
una sua possibile realizzazione. Al fine di uniformare le interfacce del livello applicativo verso
l’infrastruttura CARTE, in questo documento vengono quindi presentate le interfacce esposte
dalle Porte di Dominio verso i Servizi Applicativi.
2
Uso del Componente di Integrazione della Porta di
Dominio
Le interazioni tra i servizi applicativi e le porte delegate e applicative delle Porte di Dominio che li
ospitano devono avvenire tramite richieste SOAP 1.1. I protocolli supportati sono http ed https.
Ogni richiesta del Servizio Applicativo deve essere autenticata dalla Porta di Dominio con
l'utilizzo di autenticazione basic in caso di http o di https. E altresì possibile utilzzare certificati
X.509, in tal proposito si fa presente che :
- RT può produrre il certificato digitale utilizzando un contratto di fornitura dei certificati stipulato
con una C.A.
- CART accetta anche certificati prodotti da terzi o self signed
- CART non fornisce i certificati
3/73
In generale le interazioni tra i servizi applicativi e la porta di dominio possono avvenire in due
modi:
1. modalità trasparente: prevede che il servizio applicativo utilizzi (in caso di porta delegata) o
esponga (in caso di porta applicativa) le interfacce applicative native dei servizi,
esattamente come registrate negli accordi di servizio; in tal caso la Porta di Dominio agisce
come un proxy trasparente con funzionalità di imbustamento e sbustamento eGov dei
messaggi applicativi; utilizzando questa modalità, gli applicativi potranno continuare ad
operare esattamente come se stessero interagendo direttamente con il servizio applicativo
dell'altro Ente;
2. uso del Servizio “Integration Manager” della PdD: prevede di utilizzare le interfacce di un
apposito web service di Integrazione, messo a disposizione dalla Porta di Dominio per la
spedizione e/o la ricezione di messaggi applicativi da parte dei servizi applicativi del
proprio Dominio di Servizi.
2.1
Modalità d'uso trasparente dei Servizi
Questa modalità prevede che il servizio applicativo utilizzi (in caso di porta delegata) o esponga
(in caso di porta applicativa) le interfacce applicative native dei servizi, così come registrate negli
accordi di servizio; in tal caso la Porta di Dominio agisce come un proxy SOAP trasparente con
funzionalità di imbustamento e sbustamento eGov dei messaggi applicativi; utilizzando questa
modalità, gli applicativi continuano ad operare esattamente come se stessero interagendo
direttamente con il servizio applicativo dell'altro Ente.
L'invocazione della porta delegata in modalità trasparente può essere realizzata tramite gli
strumenti del linguaggio di programmazione nativo del servizio applicativo, utilizzando ad
esempio stub creati tramite il proprio ambiente di sviluppo Web Services (ad esempio wsdl2java in
Axis), facendo riferimento direttamente al WSDL del servizio da utilizzare, così come registrato
nell'accordo di servizio. In questo caso la principale modifica rispetto all'invocazione dell'effettivo
servizio destinazione sarà la URL utilizzata per l'invocazione http, che dovrà essere quella
corrispondente alla porta delegata del servizio esposta dalla PdD. Il codice che segue mostra un
esempio, usando Axis 1.4, di invocazione di una porta delegata usando gli stub del servizio.
try {
HelloWSServiceLocator locator = new HelloWSServiceLocator();
Locator.setHelloWorldEndpointAddress("http://nal/cart/PD/HelloWorld");
HelloWS port = locator.getHelloWorld();
String msg = port.sayHello();
} catch (AxisFault e) {
4/73
…
}
Come si può notare, è sufficiente settare l’endpoint del servizio alla URL della Porta
Delegata da indirizzare, senza ulteriori modifiche al codice applicativo. Ovviamente non è
obbligatorio utilizzare degli stub per l’invocazione del servizio, ma si può utilizzare
qualunque altra modalità supportata dal proprio ambiente di lavoro per la programmazione
di web services.
2.2
Uso del Servizio IntegrationManager
Prevede di utilizzare le interfacce di un apposito web service di Integrazione, messo a disposizione
dalla Porta di Dominio per la spedizione e/o la ricezione di messaggi applicativi da parte dei
servizi applicativi del proprio Dominio di Servizi. L'interfaccia WSDL completa dell'Integration
manager è disponibile in allegato “A”. A titolo descrittivo si mostra di seguito l'interfaccia esposta
dal Web Service, espressa in linguaggio java:
interface IntegrationManager {
SPCoopMessage invocaPortaDelegata(
String portaDelegata, SPCoopMessage msg)
SPCoopMessage sendRispostaAsincronaSimmetrica(
String portaDelegata,SPCoopMessage msg)
String[] getAllMessagesId()
String[] getAllMessagesIdByService(
String tipoServizio, String servizio, String azione)
5/73
String[] getNextMessagesId(int n)
String[] getNextMessagesIdByService(
int n, String tipoServizio, String servizio, String azione)
SPCoopMessage getMessage(String idEGov)
SPCoopMessage getMessageByReference(String riferimentoMsg)
void deleteMessage(String idEGov)
void deleteMessageByReference(String riferimentoMsg)
public void deleteAllMessages()
}
L'oggetto di base su cui lavorano le varie operazioni supportate dall’IntegrationManager è
l’SPCoopMessage, che contiene varie informazioni relative al messaggio e un array di byte
corrispondente al messaggio SOAP vero e proprio. La struttura della classe
SPCoopMessage è mostrata a titolo descrittivo in linguaggio java nel riquadro seguente.
public class SPCoopMessage implements java.io.Serializable {
public void setMessage(byte [] m)
public byte[] getMessage()
public boolean getImbustamento()
public void setImbustamento(boolean imbustamento)
public String getIDApplicativo()
public void setIDApplicativo(String applicativo)
6/73
public String getServizioApplicativo()
public void setServizioApplicativo(String servizioApplicativo)
public String getServizioApplicativoDestinatario()
public void setServizioApplicativoDestinatario(String servizioApplicativoDestinatario)
public SPCoopHeaderInfo getSpcoopHeaderInfo()
public void setSpcoopHeaderInfo(SPCoopHeaderInfo spcoopHeaderInfo)
}
Come risulta dalla struttura della classe mostrata nel riquadro precedente, l’oggetto
SPCoopMessage riferisce un ulteriore oggetto di tipo SPCoopHeaderInfo che raccoglie
tutte le informazioni relative all’header SPCoop della busta eGov accessibili dai servizi
applicativi. La struttura della classe SPCoopHeaderInfo è mostrata a titolo descrittivo in
linguaggio java nel riquadro seguente.
public class SPCoopHeaderInfo implements java.io.Serializable {
public String getTipoMittente()
public void setTipoMittente(String type )
public String getMittente()
public void setMittente(String m )
public String getTipoDestinatario()
public void setTipoDestinatario(String type )
public String getDestinatario()
7/73
public void setDestinatario(String s )
public String getServizio()
public void setServizio(String s )
public String getTipoServizio()
public void setTipoServizio(String type )
public String getAzione()
public void setAzione(String a )
public String getID()
public void setID(String id )
public String getRiferimentoMessaggio()
public void setRiferimentoMessaggio(String rif )
public String getIdCollaborazione()
public void setIdCollaborazione(String idCollaborazione)
}
2.2.1 Invocazione di una porta delegata tramite Integration Manager
Il codice che segue mostra un esempio, in Axis 1.4, di invocazione di una porta delegata usando il
servizio di IntegrationManager.
IntegrationManagerServiceLocator locator =
8/73
new IntegrationManagerServiceLocator();
locator.setIntegrationManagerEndpointAddress(IMurl);
port = locator.getIntegrationManager(username,password);
// Costruzione Messaggio SPCoop
msg = new SPCoopMessage();
// soapMessageToSend è il messaggio SOAP da spedire
// espresso come array di byte
msg.setMessage(soapMessageToSend);
try {
SPCoopMessage msgResponse = port.invocaPortaDelegata(locationPD,msg);
} catch(Exception e){
System.out.println("ClientError: "+e.getMessage());
}
2.2.2 Accesso ai messaggi ricevuti tramite Integration Manager
Il codice che segue mostra un esempio, in axis 1.4, di accesso ai messaggi ricevuti su una porta
applicativa usando il servizio di IntegrationManager.
IntegrationManagerServiceLocator locator =
new IntegrationManagerServiceLocator();
locator.setIntegrationManagerEndpointAddress(IntegrationManagerURL);
9/73
port = locator.getIntegrationManager(username,password);
String []ids = port.getAllMessagesId();
for (int i=0; i<ids.length; i++ ) {
SPCoopMessage msg = port.getMessage(ids[i]);
// processa il messaggio ricevuto come byte array ...
processMessage(msg.getMessage());
deleteMessage(ids[i]);
}
Nell’esempio precedente viene prima utilizzata l’operazione getAllMessagesId per accedere
all’elenco dei messaggi ricevuti e quindi l’operazione di getMessage per prelevare i singoli
messaggi. Dopo il processamento di un messaggio, si procede alla sua rimozione.
Oltre a questi due metodi di base, il servizio di IntegrationManager fornisce ulteriori interfacce per
gestire in vario modo i messaggi in arrivo per un SIL. Nel riquadro successivo vengono elencate le
varie interfacce utili per l’accesso ai messaggi.
String[] getAllMessagesId()
// restituisce gli identificatori di tutti i messaggi disponibili
// in coda per il SIL richiedente
String[] getAllMessagesIdByService(
String tipoServizio, String servizio, String azione)
// restituisce gli identificatori di tutti i messaggi disponibili in
// coda per il SIL corrispondente al servizio ed all’azione
// indicati in input
10/73
String[] getNextMessagesId(int n)
// restituisce i primi n identificatori di messaggi disponibili
// in coda per il SIL
String[] getNextMessagesIdByService(
int n, String tipoServizio, String servizio, String azione)
// restituisce i primi n identificatori di messaggi disponibili
// in coda per il SIL corrispondenti al servizio ed all’azione
// indicati in input
SPCoopMessage getMessage(String idEGov)
// restituisce il messaggio identificato dall’identificatore in input
SPCoopMessage getMessageByReference(String riferimentoMsg)
// restituisce il messaggio identificato dall’identificatore
// di riferimentoMessaggio in input
void deleteMessage(String idEGov)
// cancella il messaggio identificato dall’id in input
void deleteMessageByReference(String riferimentoMsg)
// cancella il messaggio identificato dall’id di riferimentoMessaggio
// in input
11/73
public void deleteAllMessages()
// cancella tutti i messaggi in coda per il SIL richiedente
3
Contenuti delle Risposte Applicative
Nel caso del profilo Sincrono, le risposte (ricevute dalla PdD nel caso di invocazioni della porta
delegata o inviate dalla PdD nel caso di invocazioni dei Servizi Applicativi abbinati alle Porte
Applicative), sono direttamente generate dai Servizi Applicativi erogatori e trasparentemente
restituiti dalla PdD ai servizi fruitori. La stessa cosa succede per i profili Asincroni Simmetrico e
Asimmetrico, che corrispondono concettualmente ad una coppia di interazioni sincrone correlate
tra loro.
Per questo motivo, l’Integration Manager non può essere usato per l’accesso ai messaggi ricevuti
dai servizi applicativi con profili Sincroni ed Asincroni. Infatti questi messaggi non possono essere
tenuti dalla Porta di Dominio in attesa di una successiva richiesta del SIL, ma devono essere
immediatamente girati al servizio applicativo per poter ottenere la risposta da girare al richiedente.
Nel caso del profilo Oneway, invece, la PdD mittente restituisce la risposta al servizio fruitore
immediatamente, senza attendere di ricevere una risposta dal servizio applicativo erogatore del
servizio. In questo caso il servizio fruitore riceverà quindi una risposta creata dalla PdD con SOAP
body vuoto.
4
La gestione degli errori nell'Interazione tra Servizio
Applicativo e Porta Delegata
In funzione del fatto che si usi la modalità di invocazione trasparente o i servizi
dell'IntegrationManager per l’invocazione di una porta delegata della Porta di Dominio, cambia il
modo in cui le condizioni di errore vengono gestite dal servizio applicativo.
Nel caso in cui si usino i servizi dell'IntegrationManager eventuali condizioni di errore generate
dalla Porta di Dominio saranno restituite all'interno di un’eccezione gestita dal servizio
IntegrationManager, il cui formato è rappresentato di seguito in linguaggio java.
public class SPCoopException {
public java.lang.String getCodiceEccezione();
public void setCodiceEccezione(java.lang.String codiceEccezione);
12/73
public java.lang.String getDescrizioneEccezione();
public void setDescrizioneEccezione(java.lang.String descrizioneEccezione);
public java.lang.String getIdentificativoFunzione();
public void setIdentificativoFunzione(java.lang.String
identificativoFunzione);
public java.lang.String getIdentificativoPorta();
public void setIdentificativoPorta(java.lang.String identificativoPorta);
public java.lang.String getOraRegistrazione();
public void setOraRegistrazione(java.lang.String oraRegistrazione);
public java.lang.String getTipoEccezione();
public void setTipoEccezione(java.lang.String tipoEccezione);
}
Le eventuali eccezioni generate dal Servizio Applicativo originale saranno invece trasportate come
SOAPFault all’interno del campo messaggio dell’oggetto SPCoopMessage.
Nel caso in cui si utilizzi la modalità trasparente, sarà invece possibile, in caso di eccezione
SOAPFault, testare il campo FaultActor per riconoscere e gestire i casi di errore dovuti
all'interazione con la porta di dominio (valore "it.toscana.regione.cart.pdd") da quelli puramente
applicativi. Nel frammento di codice seguente vediamo, a titolo di esempio, come gestire questa
situazione nel caso specifico del linguaggio java usando Axis 1.4 come web-services engine.
try {
HelloWSServiceLocator locator = new HelloWSServiceLocator();
13/73
locator.setHelloWorldEndpointAddress("http://nal/CARTe/PD/GetDate");
HelloWS port = locator.getHelloWorld();
String msg = port.sayHello();
} catch (AxisFault e) {
if("it.toscana.regione.cart.pdd".equals(e.getFaultActor())){
System.out.println("Ricevuto Messaggio di Errore PdD[" +
e.getFaultCode() + "]:");
System.out.println(e.getFaultString());
}else{
System.out.println("Ricevuto SOAPFault applicativo");
System.out.println("Actor: "+e.getFaultActor());
System.out.println("Code: "+e.getFaultCode());
System.out.println("String: "+e.getFaultString());
}
} catch (Exception e) {
System.out.println("ClientError: "+e.getMessage());
e.printStackTrace();
}
Come evidenziato nell'esempio, il particolare codice di eccezione generato dalla Porta di Dominio
potrà essere ottenuto tramite il campo FaultCode del messaggio di Fault, la descrizione dell’errore
nel campo FaultString. Il messaggio applicativo d’errore sarà presente nel campo detail del
14/73
messaggio di Fault, ottenibile nel caso dell’esempio tramite il metodo getFaultDetails della classe
AxisFault.
Ecco un esempio di messaggio di errore generato nel caso in invocazione di una porta delegata
inesistente:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:OPENSPCOOP_ORG_401</faultcode>
<faultstring>La porta delegata invocata non esiste
Location[HelloWorl] urlInvocazione[HelloWorl]
</faultstring>
<faultactor>OpenSPCoop</faultactor>
<detail>
<eGov_IT_Ecc:MessaggioDiErroreApplicativo
xmlns:eGov_IT_Ecc="http://www.cnipa.it/schemas/2003/eGovIT/Exception1_0/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<eGov_IT_Ecc:OraRegistrazione>2008-10-10T09:48:27.812</eGov_IT_Ecc:OraRegistrazione>
<eGov_IT_Ecc:IdentificativoPorta>OpenSPCoopSPCoopIT</eGov_IT_Ecc:IdentificativoPorta
>
15/73
<eGov_IT_Ecc:IdentificativoFunzione>RicezioneContenutiApplicativiWS</eGov_IT_Ecc:Ident
ificativoFunzione>
<eGov_IT_Ecc:Eccezione>
<eGov_IT_Ecc:EccezioneProcessamento
codiceEccezione="OPENSPCOOP_ORG_401" descrizioneEccezione="La porta
delegata invocata non esiste location[HelloWorl]
urlInvocazione[HelloWorl]"/>
</eGov_IT_Ecc:Eccezione>
</eGov_IT_Ecc:MessaggioDiErroreApplicativo>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
In entrambi gli approcci, in caso di errore, la Porta di Dominio restituirà gli stessi codici di errore,
elencati nella tabella seguente.
FaultCode
FaultString
CART_500
Porta di Dominio Temporaneamente non Disponibile
CART_401
Porta Delegata Inesistente
CART_402
Autenticazione Fallita
CART_403
Pattern Ricerca Porta Delegata Non Valido
CART_404
Autorizzazione Fallita
CART_405
Servizio SPCoop abbinato alla Porta Delegata Inesistente
CART_406
Nessun Messaggio disponibile per il Servizio Applicativo
16/73
CART_407
Messaggio Richiesto Inesistente
CART_4XX
Generico errore client
I servizi applicativi sono tenuti a gestire tutti gli errori generati dalla PdD, trattenendo i messaggi
che hanno generato errore per una successiva rispedizione. In particolare, in caso di errore
CART_500, il servizio applicativo è tenuto a sospendere temporaneamente per un tempo calcolato
in maniera random, la spedizione di messaggi, in modo da favorire il decongestionamento
dell’infrastruttura.
5
Aspetti di integrazione nei Profili Asincroni
I profili di collaborazione Asincroni, sia Simmetrici che Asimmetrici, al contrario degli altri profili
previsti in SPCoop (Oneway e Sincrono) richiedono due interazioni, una richiesta di servizio ed
una risposta del servizio che viene ritornata tramite una nuova interazione. Le buste eGov prodotte
sono quindi quattro (due per ogni interazione) e vengono correlate tra di loro attraverso
l’identificativo eGov. Pertanto i servizi applicativi devono necessariamente scambiare con la porta
di dominio l’informazione relativa all'id eGov utilizzato per la correlazione tra la richiesta e la
successiva risposta.
Nel caso si usi il servizio di IntegrationManager della Porta di Dominio è possibile utilizzare le
interfacce di questo servizio per lo scambio dell’id eGov necessario per la correlazione.
Nel caso in cui si utilizzi la modalità trasparente per l’invocazione dei servizi Asincroni, sarà
invece possibile utilizzare header del trasporto http, dovendo l'interfaccia applicativa rimanere
quella originale del servizio applicativo invocato.
Il codice che segue mostra un esempio di transazione asincrona asimmetrica tramite
IntegrationManager.
SPCoopMessage msg1 = new SPCoopMessage();
msg1.setMessage(soapMessageRichiesta);
// invio richiesta asincrona e prelievo dell’id di correlazione
SPCoopMessage msg1Response = port.invocaPortaDelegata(
portaDelegataRichiesta,msg1);
idEgovRichiesta = msg1Response.getID();
17/73
// Costruzione SPCoopHeaderInfo
SPCoopHeaderInfo spcoopHeaderInfo = new SPCoopHeaderInfo();
spcoopHeaderInfo.setRiferimentoMessaggio(riferimentoMessaggio);
msg.setIDApplicativo(idCorrelazioneApplicativa);
msg.setServizioApplicativo(nomeServizioApplicativo);
...
// settaggio dell’id di correlazione ed invio richiesta stato
SPCoopMessage msg2 = new SPCoopMessage();
msg2.setMessage(soapMessageRichiestaStato);
SPCoopHeaderInfo spcoopHeaderInfo2 = new SPCoopHeaderInfo();
spcoopHeaderInfo2.setRiferimentoMessaggio(idEgovRichiesta);
msg2.setSpcoopHeaderInfo(spcoopHeaderInfo2);
SPCoopMessage msg2Response =
port.invocaPortaDelegata(portaDelegataRichiestaStato, msg2);
Come evidenziato nell’esempio, la correlazione della richiesta con la risposta, avviene
prelevando l’IDEgov della prima richiesta tramite il metodo getID, e settandolo come
riferimentoMessaggio della seconda richiesta tramite il metodo setRiferimentoMessaggio.
Nel caso in cui si usi la modalità trasparente, le informazioni di correlazione potranno essere
gestite tramite le proprietà SPCoopID ed SPCoopRiferimentoMessaggio, accessibili come
mostrato nella successiva sezione Interscambio di Informazioni tra SIL e PdD. Il codice che segue
mostra un esempio di utilizzo della modalità trasparente usando gli header del protocollo http
come modalità di interscambio delle informazioni tra SIL e PdD.
URL url = new URL(UrlPortaDelegataRichiesta);
HttpURLConnection httpCon1 = (HttpURLConnection)url.openConnection();
18/73
...
OutputStream out = httpCon1.getOutputStream();
out.write(soapMessageRichiesta);
out.close();
...
String idEgov = httpCon1.getHeaderFields().get("SPCoopID");
...
url = new URL(UrlPortaDelegataRichiestaStato);
HttpURLConnection httpCon2 = (HttpURLConnection)url.openConnection();
...
httpCon2.setRequestProperty("SPCoopRiferimentoMessaggio", idEgov);
OutputStream out = httpCon2.getOutputStream();
out.write(soapMessageRichiestaStato);
out.close();
...
6
Interscambio di Informazioni tra SIL e PdD
Alcune delle informazioni parte dell’header SPCoop della busta eGov possono essere scambiate
tra il SIL e la PdD al momento dell’invocazione di una porta delegata o tra la PdD ed il SIL al
momento dell’invocazione di una porta applicativa. In particolare le informazioni in questione
variano in funzione delle specifiche precipuità degli Accordi di Servizio a cui la busta si riferisce e
sono identificate tramite le seguenti keyword:





SpCoopID
SPCoopTipoMittente
SPCoopMittente
SPCoopTipoDestinatario
SPCoopDestinatario
19/73








SPCoopTipoServizio
SPCoopServizio
SPCoopAzione
SPCoopRiferimentoMessaggio
SPCoopIdCollaborazione
SPCoopIDApplicativo
SPCoopServizioApplicativo
SPCoopServizioApplicativoDestinatario
Nel caso di uso dell’IntegrationManager, tali informazioni sono accessibili tramite le interfacce di
get/set della classe SPCoopHeaderInfo, già mostrata in precedenza.
Nel caso di uso della modalità trasparente, tali informazioni sono invece accessibili tramite tre
diverse modalità:
1. come header del trasporto http: in questo caso i nomi degli header saranno uguali alle
informazioni sopra elencate;
2. come proprietà della QUERY_STRING della URL http invocata: in questo caso il nome
della proprietà saranno uguali alle informazioni sopra elencate;
3.
come informazioni interne all’header SOAP eToscana, appositamente definito per
l’interscambio di tali informazioni nel CART; in questo caso le informazioni saranno
rappresentate in accordo all’xsd dell’header eToscana riportato in appendice ‘B’.
Va notato che la PdD del CART accetta in input e produce in output le informazioni necessarie
usando contemporaneamente tutti le 3 modalità appena elencate. E’ quindi possibile, per il
programmatore dei servizi applicativi, usare indifferentemente uno qualunque di tali modalità.
Abbiamo già mostrato un esempio d’uso dell’interscambio di informazioni tra SIL e PdD sia
tramite l’uso dell’Integration Manager che tramite l’uso di header http nella modalità trasparente,
nella precedente sezione 5 Aspetti di integrazione nei Profili Asincroni. Nel seguito vedremo
un’analogo esempio di codice, utilizzando le modalità alternative di integrazione tramite
QUERY_STRING e tramite Header SOAP eToscana.
E' importante evidenziare una nuova funzionalità della PdD associata all'utilizzo dell'attributo
“SPCoopServizioApplicativoDestinatario” dell'header eToscana: infatti mediante l'utilizzo di
questo attributo è possibile istruire la Porta di Dominio CART in modo tale che sia possibile
indirizzare un messaggio ad uno specifico SIL di destinazione associato ad un determinato Ente
erogatore.
Questo meccanismo consente di poter gestire invii di messaggi verso un Ente destinatario al quale
sono associati, per quel servizio, più SIL erogatori, selezionando un solo SIL destinatario fra quelli
possibili: la PdD consegnerà il messaggio solo al SIL indicato escludendo dalla consegna i restanti
SIL.
Infatti tramite l'uso dell'header eToscana, il mittente ha la possibilità di impostare, mediante i
meccanismi esposti nel seguito, l'attributo SPCoopServizioApplicativoDestinatario, per far si che
20/73
un determinato messaggio per il quale risulta valorizzato tale attributo, venga consegnato
esclusivamente al SIL (se esistente e associato all'Ente destinatario) indicato nell'attributo. Se il
SIL indicato non figura fra i SIL associati al soggetto erogatore, verrà generato dalla PdD un
messaggio di errore CART verso la PdD mittente.
In generale se l'attributo non risulta valorizzato, la PdD procede alla consegna a tutti i SIL
registrati per quella porta applicativa.
6.1
Integrazione tramite QUERY_STRING
URL url = new URL(UrlPortaDelegataRichiesta);
HttpURLConnection httpCon1 = (HttpURLConnection)url.openConnection();
...
OutputStream out = httpCon1.getOutputStream();
out.write(soapMessageRichiesta);
out.close();
...
String idEgov = httpCon1.getHeaderFields().get("SPCoopID");
...
url = new URL( UrlPortaDelegataRichiestaStato +
"?SPCoopRiferimentoMessaggio=" + idEgov );
HttpURLConnection httpCon2 = (HttpURLConnection)url.openConnection();
...
OutputStream out = httpCon2.getOutputStream();
21/73
out.write(soapMessageRichiestaStato);
out.close();
...
Nel codice appena mostrato si può notare come il parametro SPCoopRiferimentoMessaggio venga
passato aggiungendo un parametro della QUERY_STRING alla URL della porta delegata
invocata, anziché usando il setting degli header http.
6.2
Integrazione tramite l’uso dell’Header SOAP eToscana
URL url = new URL(UrlPortaDelegataRichiesta);
HttpURLConnection httpCon1 = (HttpURLConnection)url.openConnection();
...
OutputStream out1 = httpCon1.getOutputStream();
out1.write(soapMessageRichiesta);
out1.close();
...
InputStream responseStream = httpCon1.getInputStream();
Message response = new Message(responseStream);
responseStream.close();
...
SOAPHeaderElement headerEToscana = null;
java.util.Iterator<?> iter =
response.getSOAPHeader().examineAllHeaderElements();
while( iter.hasNext() ) {
SOAPHeaderElement headerElement = (SOAPHeaderElement) iter.next();
//Controllo Actor
22/73
if(headerElement.getActor().equals(
"http://it.regione.toscana.cart.pdd/eToscana") ) {
headerEToscana = headerElement;
break;
}
}
String idEGov = headerEToscana.getAttribute("id-egov");
...
// Preparazione dell'Header SOAP eToscana
Name name = new PrefixedQName(
"http://it.regione.toscana.cart.pdd/eToscana", "eToscana", "cart");
SOAPHeaderElement header =
new org.apache.axis.message.SOAPHeaderElement(name);
header.setActor("http://it.regione.toscana.cart.pdd/eToscana");
header.addNamespaceDeclaration("SOAP_ENV",
"http://schemas.xmlsoap.org/soap/envelope/");
// Settaggio riferimentoMessaggio per la correlazione asincrona
header.setAttribute("SPCoopRiferimentoMessaggio", idEGov);
23/73
// Aggiunta header al messaggio Soap. Si assume che il Messaggio Axis
// da spedire sia disponibile nella variabile axisMsgRichiestaStato
axisMsgRichiestaStato.getSOAPEnvelope().getHeader().addChildElement(header);
URL urlConnection = new URL(...todo...);
HttpURLConnection httpConn =
(HttpURLConnection) urlConnection.openConnection();
OutputStream out = httpConn.getOutputStream();
axisMsgRichiestaStato.writeTo(out);
out.close();
...
L'header eToscana non è un header obbligatorio per le comunicazioni tra SIL e PdD. Nel caso sia
presente in un messaggio SOAP ricevuto dal servizio di Porta Delegata, permette la
comunicazione dei valori necessari in fase di integrazione, come idendificativo di correlazione nei
profili asincroni, id di collaborazione e id di correlazione applicativa.
Di seguito viene mostrato un esempio di codice per inserire all'interno di un header eToscana un id
di correlazione applicativa:
SOAPEnvelope env = msg.getSOAPEnvelope();
SOAPHeader hdr = (SOAPHeader) env.getHeader();
if(hdr==null) {
hdr = (SOAPHeader) env.addHeader();
}
// Creazione header eToscana
Name name = new PrefixedQName("
http://it.regione.toscana.cart.pdd/eToscana","eToscana","eToscana");
24/73
org.apache.axis.message.SOAPHeaderElement header = new
org.apache.axis.message.SOAPHeaderElement(name);
header.setActor("http://it.regione.toscana.cart.pdd/eToscana");
header.setMustUnderstand(false);
header.addNamespaceDeclaration("SOAP_ENV","
http://schemas.xmlsoap.org/soap/envelope/");
header.setAttribute("SPCoopIDApplicativo",idCorrelazioneApplicativa);
hdr.addChild(header);
Lo stesso header viene utilizzato per le interazioni tra Porta di Dominio e SIL per la
comunicazione dei valori significativi in fase di consegna del messaggio, come il servizio e
l'azione SPCoop a cui il messaggio è riferito, l'identificativo eGov, ed eventuali identificativi di
correlazione per i profili asincroni o per correlazione applicativa.
7
uso del meccamismo dei Filtri JMS
Attualmente i proxy applicativi, utilizzando il framework FCA, possono associare dei filtri ai
messaggi pubblicati via JMS in modo che i sottoscrittori possano filtrare la ricezione di tali
messaggi in base a determinate proprietà stabilite in fase di progettazione dell'applicazione.
Questa funzionalità, inizialmente sviluppata per emulare l'analogo comportamento dell'FCA, è
stata poi resa accessibile anche ai SIL che non usano i proxy applicativi ma direttamente la Porta di
Dominio.
In tal caso il SIL pubblicatore dovrà comunicare alla Porta di Dominio i valori delle proprietà usate
come filtri, nella forma di una sequenza di triple del tipo:
<nome proprietà, valore proprietà, operatore>
dove l’operatore può assumere uno dei seguenti valori: =,<,>,<>,<=,>=,LIKE.
ATTENZIONE: quando viene utilizzato l’operatore LIKE, il valore della proprietà dovrà
contenere esclusivamente caratteri alfanumerici o il carattere ‘#’. Il matching, in caso di uso
dell’operatore LIKE, avverrà se il valore della proprietà risulta essere una sottostringa del valore
inserito dal pubblicatore per quella proprietà.
25/73
7.1
Impostazione delle proprietà da parte del SIL Pubblicatore
L’impostazione delle proprietà da parte dei SIL pubblicatori può avvenire usando l'API dell'FCA
Sun, in particolare tramite la feature delle msgRules prevista dall'FCA oppure, nel caso di
applicazioni che non usino l'FCA, inserendo nel messaggio SOAP da spedire un header nel
formato eToscana.
N.B.: Benché l’uso sia deprecato, per ragioni di backward compatibility, in alternativa all’header
eToscana è possibile utilizzare un header analogo a quello usato dall'emulatore FCA, che contiene
la specifica dei filtri come nel formato xml seguente:
<a:Intestazione soapenv:actor="http://it.regione.toscana.cart.pdd/fca"
soapenv:mustUnderstand="1"
xmlns:a="http://it.regione.toscana.cart.pdd/fca/Busta">
<a:IntestazioneMessaggio>
<a:Filters>
<a:Filter>
<a:Key>Chiave1</a:Key>
<a:Value>Value12</a:Value>
</a:Filter>
<a:Filter>
<a:Key>Chiave2</a:Key>
<a:Value>Value2</a:Value>
</a:Filter>
<a:Filter>…</a:Filter>
…
</a:Filters>
</a:IntestazioneMessaggio>
</a:Intestazione>
26/73
Integrando invece la gestione dei filtri nell'header eToscana, questo header diventa l'unico con il
quale gli sviluppatori dovranno interagire per qualunque esigenza di programmazione avanzata dei
servizi CART.
Di seguito viene mostrato un esempio di codice per inserire all'interno di un header eToscana uno
o piu' filtri:
private void addHeaderEToscana(Message msg,String[] key,String []values) throws Exception{
if(key==null || values==null || key.length!=values.length)
throw new Exception("Parametri non validi");
SOAPEnvelope env = msg.getSOAPEnvelope();
SOAPHeader hdr = (SOAPHeader) env.getHeader();
if(hdr==null){
hdr = (SOAPHeader) env.addHeader();
}
// Creazione header eToscana
Name name = new PrefixedQName("
http://it.regione.toscana.cart.pdd/eToscana","eToscana","eToscana");
org.apache.axis.message.SOAPHeaderElement header = new
org.apache.axis.message.SOAPHeaderElement(name);
header.setActor("http://it.regione.toscana.cart.pdd/eToscana");
header.setMustUnderstand(false);
header.addNamespaceDeclaration("SOAP_ENV",
"http://schemas.xmlsoap.org/soap/envelope/");
MessageElement filters =
(MessageElement) header.addChildElement("Filters");
for(int i=0; i<key.length; i++){
MessageElement filter =
27/73
(MessageElement) filters.addChildElement("Filter");
filter.setAttribute("Key",key[i]);
filter.setAttribute("Value",values[i]);
}
hdr.addChild(header);
}
8
Proxy CART
E' stato realizzato un proxy applicativo in grado di inviare copia dei messaggi in partenza ad un
servizio destinatario terzo.
ü
ü
ü
Realizza la funzionalità di invio del messaggio per conoscenza anche in caso di profili
Sincroni e Asincroni e non solo per comunicazioni di tipo Oneway. Il servizio per
conoscenza resterà in ogni caso un messaggio Oneway, corrispondente al messaggio di
input della comunicazione originale.
Realizza l'autenticazione del SIL mittente, per il profilo HTTP basic.
Gestisce gli errori; eventuali errori nella gestione del messaggio in fase di accettazione
da parte della Porta di Dominio vengono notificati al mittente originale.
La configurazione del proxyCART avviene tramite un registro locale tenuto su filesystem, che
permette di configurare in maniera differenziata il comportamento del proxy per ogni diversa
invocazione di servizio effettuata dall'utente.
9
Mediatori TSB
Apache Synapse è un motore di mediazione ed un ESB (Enterprise Service Bus) che si interpone
nello scambio di messaggi tra applicazioni enterprise. Secondo la più' comune definizione, un
Service Bus si configura come il layer superiore di un sistema di messaggistica enterprise il cui
scopo principale è quello di disaccoppiare i servizi che inviano messaggi, dal tipo di trasporto
scelto per l'invio di questi. Un motore di mediazione invece, facilita la comunicazione tra servizi
potenzialmente incompatibili tra loro, attraverso la gestione delle loro interazioni, e la
trasformazione dei messaggi che questi si scambiano.
28/73
Da queste semplici definizioni discendono quindi le principali funzionalità' esposte da Apache
Synapse, e che possiamo riassumere nella lista seguente:
•
Interconnettere applicazioni che comunicano con trasporti differenti (JMS, SMTP,
HTTP, HTTPS, etc.)
•
Gestire i flussi di messaggi che le applicazioni si scambiano nelle loro interazioni
•
Trasformare messaggi in formati compatibili tra le varie applicazioni (XSLT,
Xquery)
Ovviamente perché tali funzionalità possano essere garantite nel modo migliore possibile, Synapse
è ampiamente basato su standard largamente riconosciuti ed adottati in ambiente Enterprise.
Attualmente le possibilità' di interconnettere servizi basati su trasporti di tipo differente, includono
trasporti tra i più comuni come: HTTP, HTTPS JMS, FTP, POP3/IMAP/SMTP. Inoltre i messaggi
possono essere scambiati in formato XML, SOAP (versioni 1.1 ed 1.2), puro testo e binario, con la
possibilità di trasformazioni e conversioni da un formato all'altro.
La mediazione di messaggi può avvenire in due modalità differenti:
1.
MM (Message Mediation) che applica regole di trasformazione e di mediazione a tutti
i messaggi che fluiscono all'interno del Bus;
2.
SM (Service Mediation) che applica le regole di trasformazione e di mediazione a
tutti e soli i messaggi indirizzati ad uno specifico servizio (messo a disposizione da synapse
attraverso un'apposita URI)
La differenza sostanziale tra questi due approcci è che con il MM, l'applicazione ignora che i
messaggi che invia vengano mediati, mentre nel SM l'applicazione sceglie quali regole di
mediazione devono essere applicate ai messaggi che invia, indirizzandoli verso una URI piuttosto
che verso un'altra.
9.1
Il linguaggio di configurazione
Syanpse deve essere istruito su come mediare i messaggi attraverso un linguaggio di
configurazione che indichi quali trasformazioni e operazioni di mediazione effettuare. Il
linguaggio di configurazione segue la sintassi XML ed i suoi costrutti definiscono gli elementi di
base (mediatori, sequenze di mediazioni, endpoint, etc), che possono essere combinati tra loro per
formare regole di diversa complessità. Le regole di mediazione scritte nel linguaggio di
configurazione di synapse, sono salvate in un file di configurazione che viene letto dal Bus quando
questo viene avviato.
L'elenco seguente vuole mettere in evidenza alcuni dei costrutti più significativi messi a
disposizione dal linguaggio di configurazione di Synapse, allo scopo di chiarificare quanto verrà
esposto negli esempi che saranno proposti nei paragrafi successivi:
1.
inSequence/outSequence: questo mediatore permette di selezionare solo i messaggi
secondo il loro verso di percorrenza (richiesta o risposta rispettivamente). Ai messaggi
selezionati in questa maniera viene applicata la sequenza di mediazioni specificata dentro il
costrutto;
2.
switch: questo mediatore permette di selezionare i messaggi sul valore di
un'espressione XPATH (o anche di un espressione regolare), valutata sul messaggio in
29/73
transito. Dentro il costrutto è possibile specificare i valori che è possibile aspettarsi dalla
valutazione dell'espressione e quale sequenza di mediazione applicare al messaggio nel
caso l'espressione coincida col valore specificato;
3.
clone: questo mediatore consente di creare uno o più messaggi completamente
identici a quello in transito da trattare parallelamente ad esso. Inoltre può essere specificata
una sequenza di mediazione da applicare a messaggi cloni;
4.
property: questo mediatore imposta una proprietà ad un valore (costante o risultato di
un espressione XPATH) che verrà posta nel MC (Message Context) del messaggio in
transito;
5.
send: questo mediatore invia il messaggio verso un certo endpoint, che può essere
specificato esplicitamente o inferito da synapse attraverso le proprietà del messaggio;
6.
drop: il messaggio in gestione viene scartato;
7.
get-property: questa è una funzionalità builtin di synapse che aiuta a recuperare
proprietà associate al contesto del messaggio;
8.
xslt: applica un foglio di stile xslt al messaggio in transito.
9.2
Alcuni Esempi
Prima di mostrare alcuni esempi d'uso del TSB nel contesto complessivo del CART, mostriamo un
semplice esempio di configurazione xml di un proxy in Synapse. L'xml seguente descrive il proxy
HelloWorldTSB, la cui funzione sarà quella di trasformare un messaggio in transito, prima di
reindirizzarlo al servizio target.
<definitions xmlns="http://ws.apache.org/ns/synapse">
<proxy
name="HelloWorldTSB"
<description>Hello
<target>
<inSequence>
<xslt key="file:/etc/transform.xslt"/>
</inSequence>
<endpoint name="HelloWorld">
<address uri="http://localhost/services/HelloWorld"/>
</endpoint>
</target>
</proxy>
</definitions>
>
World</description>
Una volta deployata nel TSB la descrizione di cui sopra, lo specifico proxy che ne implementa la
logica, sarà invocabile alla url http://tsb-server/proxy/HelloWorldTSB. Associando questa url alla
porta applicativa del servizio SPCoop HelloWorld si otterrebbe quindi che al SIL erogatore
originale arrivi il messaggio trasformato.
9.3
L'esempio delle Comunicazioni Obbligatorie
Riprendendo l'esempio mostrato nella sezione dell'Architettura Generale, vediamo ora un esempio
più significativo di proxy che realizza la trasformazione del contenuto necessario a
ProvinciaFirenze per fruire del servizio ComunicazioniObbligatorie dopo il presunto
aggiornamento delle interfacce applicative del servizio effettuato da BNCL.
<definitions xmlns="http://ws.apache.org/ns/synapse">
30/73
<proxy
name="AggiornamentoComunicazioniObbligatorie"
>
<description>Aggiunta
del
codice
regionele</description>
<target>
<inSequence>
<xslt key="file:/etc/aggiuntaCodiceRegionale.xslt"/>
</inSequence>
<endpoint name="InvocazioneComunicazioniObbligatorie">
<address
uri="http://localhost/cart/PD/SPCRegioneToscana/SPCBNCL/SPCComunicazioniObbligatorie
"/>
</endpoint>
<outSequence>
<xslt key="file:/etc/rimozioneCodiceRegionale.xslt"/>
</outSequence>
</target>
</proxy>
</definitions>
Il percorso complessivo del messaggio relativo alla comunicazione obbligatoria è costituito dai
seguenti passaggi:
1.
invocazione
della
porta
delegata
SPCProvinciaFirenze/SPCRegioneToscana/SPCInoltroComunicazioniObbligatorie da parte
del SIL fruitore della PdD di ProvinciaFirenze;
2.
richiesta sincrona ricevuta dalla PdD di RegioneToscana e gestita tramite
l'invocazione del Proxy TSB 'AggiornamentoComunicazioniObbligatorie' agganciato come
servizio
applicativo
alla
porta
applicativa
istanziata
per
il
servizio
InoltroComunicazioniObbligatorie;
3.
il Proxy TSB trasforma il messaggio xml, aggiungendo il campo 'CodiceRegionale'
con valore il codice della Regione Toscana;
4.
invocazione
della
porta
delegata
SPCRegioneToscana/SPCBNCL/SPCComunicazioniObbligatorie da parte del Proxy TSB
della PdD di RegioneToscana;
5.
richiesta sincrona ricevuta dalla PdD di BNCL e gestita tramite l'invocazione del
servizio applicativo di ComunicazioniObbligatorie;
6.
invio risposta sincrona da BNCL verso RegioneToscana;
7.
risposta sincrona ricevuta dalla PdD di RegioneToscana e ritornata al Proxy TSB;
8.
il proxy TSB trasforma il messaggio xml, rimuovendo il campo 'CodiceRegionale' e
ritorna il messaggio di risposta a RegioneToscana;
9.
il messaggio di risposta viene restituito a ProvinciaFirenze;
9.4
Utilizzo di Synapse per il TSB
Come evidenziato nel capitolo precedente, Synapse permette di effettuare operazioni di
trasformazione dei messaggi tramite la definizione di un file XML. Le trasformazioni dei messaggi
avvengono tramite l'invocazione di mediatori pre-esistenti già forniti. Tali mediatori però non
coprono tutte le funzionalità necessarie in CARTe; fortunatamente Synapse fornisce un ampio e
complesso ambiente di sviluppo che ne permette la realizzazione per le esigenze del mondo
CARTe. Di seguito viene descritto l'ambiente di sviluppo fornito con Synapse.
31/73
Synapse consente di effettuare il deploy dei proxy services tramite il file synapse.xml. Vediamo
ad esempio il contenuto di synapse.xml nel caso del TSB rilasciato:
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
<!-- Trasformazioni XSL -->
<proxy name="ProxyXSLT" transports="http">
<target>
<inSequence>
<EToscanaHeaderLog/>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
</proxy>
<!-- Invio in copia -->
<proxy name="ProxyCC" transports="http">
<target>
<inSequence>
<EToscanaInvioPerConoscenza/>
</inSequence>
<outSequence>
<send/>
</outSequence>
32/73
</target>
</proxy>
<!-- Trasformazioni di Profilo di Collaborazione -->
<!-- Da servizio OneWay a servizio Sincrono -->
<proxy name="ProxyOW2S" transports="http">
<target>
<inSequence>
<EToscanaOneWay2Sincrono/>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
</proxy>
<!-- Da servizio Sincrono a servizio Asincrono Simmetrico -->
<proxy name="ProxyASRichiesta" transports="http">
<target>
<inSequence>
<EToscanaSincrono2AsincronoSimmetrico/>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
33/73
</proxy>
<proxy name="ProxyASRisposta" transports="http">
<target>
<inSequence>
<EToscanaSincrono2AsincronoSimmetrico rispostaAsincrona="true" />
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
</proxy>
<!-- Da servizio Sincrono a servizio Asincrono Asimmetrico -->
<proxy name="ProxyAARichiesta" transports="http">
<target>
<inSequence>
<EToscanaSincrono2AsincronoAsimmetrico/>
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
</proxy>
<proxy name="ProxyAARisposta" transports="http">
<target>
34/73
<inSequence>
<EToscanaSincrono2AsincronoAsimmetrico rispostaAsincrona="true" />
</inSequence>
<outSequence>
<send/>
</outSequence>
</target>
</proxy>
</definitions>
Synapse fornisce un ampio SET di API Java per la scrittura di Mediatori custom. La principale
interfaccia per la programmazione dei mediatori custom è il MessageContext che contiene tutte le
informazioni associate ad un messaggio, oltre al messaggio stesso. Ciascun messaggio, che arriva a
Synapse, viene wrappato dentro un'istanza di MessageContext, e passato tra i vari mediatori
presenti nella catena di ingresso e di uscita.
Di seguito viene descritta l'interfaccia del MessageContext con i principali metodi:
package org.apache.synapse;
import ...
public interface MessageContext {
/**
* Get a reference to the current SynapseConfiguration
*
* @return the current synapse configuration
*/
public SynapseConfiguration getConfiguration();
/**
35/73
* Set or replace the Synapse Configuration instance to be used.
* May be used to
* programatically change the configuration at runtime etc.
*
* @param cfg The new synapse configuration instance
*/
public void setConfiguration(SynapseConfiguration cfg);
/**
* Returns a reference to the host Synapse Environment
* @return the Synapse Environment
*/
public SynapseEnvironment getEnvironment();
/**
* Sets the SynapseEnvironment reference to this context
* @param se the reference to the Synapse Environment
*/
public void setEnvironment(SynapseEnvironment se);
/**
* Get the value of a custom (local) property set on the message instance
* @param key key to look up property
* @return value for the given key
*/
public Object getProperty(String key);
/**
* Set a custom (local) property with the given name
* on the message instance
* @param key key to be used
36/73
* @param value value to be saved
*/
public void setProperty(String key, Object value);
/**
* Returns the Set of keys over the properties on this message context
* @return a Set of keys over message properties
*/
public Set getPropertyKeySet();
/**
* Get the SOAP envelope of this message
* @return the SOAP envelope of the message
*/
public SOAPEnvelope getEnvelope();
/**
* Sets the given envelope as the current SOAPEnvelope for this message
* @param envelope the envelope to be set
* @throws org.apache.axis2.AxisFault on exception
*/
public void setEnvelope(SOAPEnvelope envelope) throws AxisFault;
/**
* SOAP message related getters and setters
*/
public ....get/set()...
}
L'interfaccia MessageContext è basata su Axis2 MessageContext interface, e usa le classi
EndpointReference e SOAPEnvelope fornite con Axis2. Lo scopo dell'interfaccia è rappresentare
un messaggio come fosse un flusso che viaggia attraverso il sistema Synapse. I messaggi binari
saranno incapsulati con MTOM o SwA attachments usando AXIOM object model.
37/73
L'ambiente di sviluppo fornisce anche l'interfaccia che un mediator edeve implementare:
package org.apache.synapse;
import org.apache.synapse.MessageContext;
/**
* All Synapse mediators must implement this Mediator interface.
* As a message passes through the synapse system,
* each mediator's mediate() method is invoked in the
* sequence/order defined in the SynapseConfiguration.
*/
public interface Mediator {
/**
* Invokes the mediator passing the current message for mediation. Each
* mediator performs its mediation action, and returns true if mediation
* should continue, or false if further mediation should be aborted.
*
* @param synCtx the current message for mediation
* @return true if further mediation should continue
*/
public boolean mediate(MessageContext synCtx);
/**
* This is used for debugging purposes and exposes the type of the current
* mediator for logging and debugging purposes
* @return a String representation of the mediator type
*/
public String getType();
}
38/73
Un mediatore può leggere e/o modificare il SynapseMessage come desidera, ad esempio
modificando il SOAPHeader o SOAPBody.
In caso il metodo mediate() ritorna false, significa che il mediator vuole segnalare a Synapse di
non processare ulteriormente il messaggio. Ad esempio un mediatore che funge da FiltroAntiVirus
può decidere che il messaggio è pericoloso e quindi non farlo processare ulteriormente dagli altri
mediatori che lo seguono nella catena.
Un mediatore può essere ulteriormente classificabile in Synapse, poiché si possono distinguere
mediatori che sono Nodi (contengono altri mediatori figli) e mediatori che sono Foglie (mediatori
che non hanno altri mediatori figli). Un mediatore Nodo deve implementare l'interfaccia
org.apache.synapse.api.ListMediator
o
estendere
da
org.apache.synapse.mediators.AbstractListMediator. L'interfaccia definisci le API per la gestione
dei mediatori figli:
package org.apache.synapse.mediators;
import java.util.List;
/**
* The List mediator executes a given sequence/list of child mediators
*/
public interface ListMediator extends Mediator {
/**
* Appends the specified mediator to the end of this mediator's (children) list
* @param m the mediator to be added
* @return true (as per the general contract of the Collection.add method)
*/
public boolean addChild(Mediator m);
/**
* Appends all of the mediators in the specified collection to the end of this mediator's
(children)
* list, in the order that they are returned by the specified collection's iterator
* @param c the list of mediators to be added
* @return true if this list changed as a result of the call
39/73
*/
public boolean addAll(List c);
/**
* Returns the mediator at the specified position
* @param pos index of mediator to return
* @return the mediator at the specified position in this list
*/
public Mediator getChild(int pos);
/**
* Removes the first occurrence in this list of the specified mediator
* @param m mediator to be removed from this list, if present
* @return true if this list contained the specified mediator
*/
public boolean removeChild(Mediator m);
/**
* Removes the mediator at the specified position in this list
* @param pos the index of the mediator to remove
* @return the mediator previously at the specified position
*/
public Mediator removeChild(int pos);
/**
* Return the list of mediators of this List mediator instance
* @return the child/sub mediator list
*/
public List getList();
40/73
}
Ogni mediatore attinge la sua configurazione dal registro/configurazione di Synapse.
è comunque possibile scrivere una configurazione custom per l'implementazione di un mediatore
attraverso la scrittura di una MediatorFactory realizzata ad hoc, in modo che la factory crei e
configuri il mediator custom, attingendo i dati di inizializzazione da qualsiasi fonte desidera.
Di seguito l'interfaccia di una mediatorFactory:
package org.apache.synapse.config.xml;
import ...
/**
* A mediator factory capable of creating an instance of a mediator through a given
* XML should implement this interface
*/
public interface MediatorFactory {
/**
* Creates an instance of the mediator using the OMElement
* @param elem
* @return the created mediator
*/
public Mediator createMediator(OMElement elem);
/**
* The QName of this mediator element in the XML config
* @return QName of the mediator element
*/
public QName getTagQName();
}
Nel paragrafo 5.2 verranno descritti i mediatori personalizzati che verranno sviluppati per Cart-E
Di seguito viene descritto un'esempio di utilizzo di un mediatore Cart-E sviluppato ad hoc per
processare una lista di url di destinazioni a cui inviare il messaggio ricevuto.
<definitions xmlns="http://ws.apache.org/ns/synapse">
41/73
<proxy
name="ProxyCartMediator"
<target>
<inSequence>
<class name="it.regione.toscana.synapse.ProxyCartMediator ">
>
<property name="destinations" value="URL1,URL2,URL3"/>
</class>
</inSequence>
<endpoint name="InvocazioneComunicazioniObbligatorie">
<address uri="http://URL_SERVIZIO_ORIGINALE "/>
</endpoint>
<outSequence>
<send/>
</outSequence>
</target>
</proxy>
</definitions>
Il vasto set di API fornito da Synapse utilizzabile per la scrittura dei mediatori personalizzati viene
descritto di seguito, evidenziando i principali package:
Packages
org.apache.synapse
Gestione di Base
org.apache.synapse.config
Configurazione di Synapse
org.apache.synapse.config.xml.endpoints
Creazione di endpoint normali, per failover,
WSDL, Load balance....
org.apache.synapse.core.axis2
Funzionalità ereditata da Axis2 per gestire
SOAP e WSDL 1.1 e 1.2
org.apache.synapse.mediators
Mediatori generici
org.apache.synapse.mediators.bsf
Linguaggi di Scripts
org.apache.synapse.mediators.builtin
Mediatori built in per log, gestione flussi, cache
org.apache.synapse.mediators.db
Mediatori per ricerche o salvataggio di dati su
Database, anche tramite database connections
pools
org.apache.synapse.mediators.eip
Mediatori per splittare o aggregare messaggi
42/73
org.apache.synapse.mediators.filters
Filtri
org.apache.synapse.mediators.spring
Mediatori per utilizzare Spring
org.apache.synapse.mediators.throttle
Mediatori per il throttling della trasmissione dei
messaggi
org.apache.synapse.mediators.transform
Mediatori per trasformazioni XSLT, Fault o
Header
org.apache.synapse.mediators.xquery
Mediatori per XQuery
org.apache.synapse.registry
Utilizzo di registri/repository per conservare
fogli di stile XSLT, schemi XSD ...
org.apache.synapse.startup.quartz
Timers
org.apache.synapse.transport.amqp
Gestione specifica del broker JMS AMQ
org.apache.synapse.transport.base
Gestione di base per il trasporto dei messaggi
org.apache.synapse.transport.base.threads
Pool di thread per la trasmissione dei messaggi
Supporto per FIX (Financial Information
eXchange) protocol
org.apache.synapse.transport.fix
org.apache.synapse.transport.jms
Gestione protocollo JMS
org.apache.synapse.transport.mail
Gestione del trasporto di e-Mail con
POP3/SMTP/IMAP
org.apache.synapse.transport.nhttp
Trasportto HTTP/S non bloccante basato
su Apache HttpCore esecuzioni veloci e
per supportare centinaia di connessioni in
presenza di alta concorrenza con costante
utilizzo della memoria
org.apache.synapse.transport.pipe
Trasporto per leggere messaggi da UNIX pipe.
org.apache.synapse.transport.udp
UDP protocol.
org.apache.synapse.transport.vfs
Virtual File System
org.apache.synapse.util
Utilities generiche
43/73
org.apache.synapse.util.xpath
Supporto a espressioni XPATH
Per ulteriori approfondimenti sull'ambiente di sviluppo di Synapse consultareil sito web
http://synapse.apache.org/
44/73
Allegato A: Interfaccia WSDL del Servizio di
IntegrationManager
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
targetNamespace="http://services.pdd.openspcoop.org"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="http://services.pdd.openspcoop.org" xmlns:intf="http://services.pdd.openspcoop.org"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema
targetNamespace="http://services.pdd.openspcoop.org"
xmlns="http://www.w3.org/2001/XMLSchema">
elementFormDefault="qualified"
<element name="getMessage">
<complexType>
<sequence>
<element name="idEGov" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="getMessageResponse">
<complexType>
<sequence>
<element name="getMessageReturn" type="impl:SPCoopMessage"/>
</sequence>
</complexType>
45/73
</element>
<complexType name="SPCoopHeaderInfo">
<sequence>
<element name="ID" nillable="true" type="xsd:string"/>
<element name="azione" nillable="true" type="xsd:string"/>
<element name="destinatario" nillable="true" type="xsd:string"/>
<element name="idCollaborazione" nillable="true" type="xsd:string"/>
<element name="mittente" nillable="true" type="xsd:string"/>
<element name="riferimentoMessaggio" nillable="true" type="xsd:string"/>
<element name="servizio" nillable="true" type="xsd:string"/>
<element name="tipoDestinatario" nillable="true" type="xsd:string"/>
<element name="tipoMittente" nillable="true" type="xsd:string"/>
<element name="tipoServizio" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<complexType name="SPCoopMessage">
<sequence>
<element name="IDApplicativo" nillable="true" type="xsd:string"/>
<element name="imbustamento" type="xsd:boolean"/>
<element name="message" nillable="true" type="xsd:base64Binary"/>
<element name="servizioApplicativo" nillable="true" type="xsd:string"/>
<element name="servizioApplicativoDestinatario" nillable="true" type="xsd:string" />
<element name="spcoopHeaderInfo" nillable="true" type="impl:SPCoopHeaderInfo"/>
</sequence>
</complexType>
46/73
<complexType name="SPCoopException">
<sequence>
<element name="codiceEccezione" nillable="true" type="xsd:string"/>
<element name="descrizioneEccezione" nillable="true" type="xsd:string"/>
<element name="identificativoFunzione" nillable="true" type="xsd:string"/>
<element name="identificativoPorta" nillable="true" type="xsd:string"/>
<element name="oraRegistrazione" nillable="true" type="xsd:string"/>
<element name="tipoEccezione" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<element name="fault" type="impl:SPCoopException"/>
<element name="deleteMessage">
<complexType>
<sequence>
<element name="idEGov" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="deleteMessageResponse">
<complexType/>
</element>
<element name="getAllMessagesId">
<complexType/>
</element>
<element name="getAllMessagesIdResponse">
47/73
<complexType>
<sequence>
<element maxOccurs="unbounded" name="getAllMessagesIdReturn" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="getAllMessagesIdByService">
<complexType>
<sequence>
<element name="tipoServizio" type="xsd:string"/>
<element name="servizio" type="xsd:string"/>
<element name="azione" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="getAllMessagesIdByServiceResponse">
<complexType>
<sequence>
<element
type="xsd:string"/>
maxOccurs="unbounded"
</sequence>
</complexType>
</element>
<element name="getNextMessagesId">
<complexType>
48/73
name="getAllMessagesIdByServiceReturn"
<sequence>
<element name="counter" type="xsd:int"/>
</sequence>
</complexType>
</element>
<element name="getNextMessagesIdResponse">
<complexType>
<sequence>
<element maxOccurs="unbounded" name="getNextMessagesIdReturn" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="getNextMessagesIdByService">
<complexType>
<sequence>
<element name="counter" type="xsd:int"/>
<element name="tipoServizio" type="xsd:string"/>
<element name="servizio" type="xsd:string"/>
<element name="azione" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="getNextMessagesIdByServiceResponse">
<complexType>
<sequence>
49/73
<element
type="xsd:string"/>
maxOccurs="unbounded"
name="getNextMessagesIdByServiceReturn"
</sequence>
</complexType>
</element>
<element name="getMessageByReference">
<complexType>
<sequence>
<element name="riferimentoMsg" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="getMessageByReferenceResponse">
<complexType>
<sequence>
<element name="getMessageByReferenceReturn" type="impl:SPCoopMessage"/>
</sequence>
</complexType>
</element>
<element name="deleteMessageByReference">
<complexType>
<sequence>
<element name="riferimentoMsg" type="xsd:string"/>
</sequence>
</complexType>
50/73
</element>
<element name="deleteMessageByReferenceResponse">
<complexType/>
</element>
<element name="deleteAllMessages">
<complexType/>
</element>
<element name="deleteAllMessagesResponse">
<complexType/>
</element>
<element name="invocaPortaDelegata">
<complexType>
<sequence>
<element name="portaDelegata" type="xsd:string"/>
<element name="msg" type="impl:SPCoopMessage"/>
</sequence>
</complexType>
</element>
<element name="invocaPortaDelegataResponse">
<complexType>
<sequence>
<element name="invocaPortaDelegataReturn" type="impl:SPCoopMessage"/>
</sequence>
</complexType>
</element>
51/73
<element name="invocaPortaDelegataPerRiferimento">
<complexType>
<sequence>
<element name="portaDelegata" type="xsd:string"/>
<element name="msg" type="impl:SPCoopMessage"/>
<element name="riferimentoMessaggio" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="invocaPortaDelegataPerRiferimentoResponse">
<complexType>
<sequence>
<element name="invocaPortaDelegataPerRiferimentoReturn" type="impl:SPCoopMessage"/>
</sequence>
</complexType>
</element>
<element name="sendRispostaAsincronaSimmetrica">
<complexType>
<sequence>
<element name="portaDelegata" type="xsd:string"/>
<element name="msg" type="impl:SPCoopMessage"/>
</sequence>
</complexType>
</element>
<element name="sendRispostaAsincronaSimmetricaResponse">
52/73
<complexType>
<sequence>
<element name="sendRispostaAsincronaSimmetricaReturn" type="impl:SPCoopMessage"/>
</sequence>
</complexType>
</element>
<element name="sendRichiestaStatoAsincronaAsimmetrica">
<complexType>
<sequence>
<element name="portaDelegata" type="xsd:string"/>
<element name="msg" type="impl:SPCoopMessage"/>
</sequence>
</complexType>
</element>
<element name="sendRichiestaStatoAsincronaAsimmetricaResponse">
<complexType>
<sequence>
<element
type="impl:SPCoopMessage"/>
name="sendRichiestaStatoAsincronaAsimmetricaReturn"
</sequence>
</complexType>
</element>
</schema>
</wsdl:types>
53/73
<wsdl:message name="invocaPortaDelegataPerRiferimentoResponse">
<wsdl:part
name="parameters"/>
element="impl:invocaPortaDelegataPerRiferimentoResponse"
</wsdl:message>
<wsdl:message name="getNextMessagesIdByServiceRequest">
<wsdl:part element="impl:getNextMessagesIdByService" name="parameters"/>
</wsdl:message>
<wsdl:message name="getMessageRequest">
<wsdl:part element="impl:getMessage" name="parameters"/>
</wsdl:message>
<wsdl:message name="invocaPortaDelegataPerRiferimentoRequest">
<wsdl:part element="impl:invocaPortaDelegataPerRiferimento" name="parameters"/>
</wsdl:message>
<wsdl:message name="invocaPortaDelegataRequest">
<wsdl:part element="impl:invocaPortaDelegata" name="parameters"/>
</wsdl:message>
<wsdl:message name="getNextMessagesIdRequest">
<wsdl:part element="impl:getNextMessagesId" name="parameters"/>
</wsdl:message>
<wsdl:message name="deleteAllMessagesResponse">
<wsdl:part element="impl:deleteAllMessagesResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="getAllMessagesIdByServiceRequest">
<wsdl:part element="impl:getAllMessagesIdByService" name="parameters"/>
</wsdl:message>
54/73
<wsdl:message name="getAllMessagesIdByServiceResponse">
<wsdl:part element="impl:getAllMessagesIdByServiceResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="getMessageResponse">
<wsdl:part element="impl:getMessageResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="sendRispostaAsincronaSimmetricaResponse">
<wsdl:part element="impl:sendRispostaAsincronaSimmetricaResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="sendRichiestaStatoAsincronaAsimmetricaResponse">
<wsdl:part
name="parameters"/>
element="impl:sendRichiestaStatoAsincronaAsimmetricaResponse"
</wsdl:message>
<wsdl:message name="deleteMessageByReferenceRequest">
<wsdl:part element="impl:deleteMessageByReference" name="parameters"/>
</wsdl:message>
<wsdl:message name="invocaPortaDelegataResponse">
<wsdl:part element="impl:invocaPortaDelegataResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="getNextMessagesIdByServiceResponse">
<wsdl:part element="impl:getNextMessagesIdByServiceResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="sendRichiestaStatoAsincronaAsimmetricaRequest">
<wsdl:part element="impl:sendRichiestaStatoAsincronaAsimmetrica" name="parameters"/>
</wsdl:message>
55/73
<wsdl:message name="deleteMessageRequest">
<wsdl:part element="impl:deleteMessage" name="parameters"/>
</wsdl:message>
<wsdl:message name="getAllMessagesIdResponse">
<wsdl:part element="impl:getAllMessagesIdResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="getNextMessagesIdResponse">
<wsdl:part element="impl:getNextMessagesIdResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="SPCoopException">
<wsdl:part element="impl:fault" name="fault"/>
</wsdl:message>
<wsdl:message name="deleteAllMessagesRequest">
<wsdl:part element="impl:deleteAllMessages" name="parameters"/>
</wsdl:message>
<wsdl:message name="deleteMessageByReferenceResponse">
<wsdl:part element="impl:deleteMessageByReferenceResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="deleteMessageResponse">
<wsdl:part element="impl:deleteMessageResponse" name="parameters"/>
</wsdl:message>
<wsdl:message name="getMessageByReferenceResponse">
<wsdl:part element="impl:getMessageByReferenceResponse" name="parameters"/>
</wsdl:message>
56/73
<wsdl:message name="getAllMessagesIdRequest">
<wsdl:part element="impl:getAllMessagesId" name="parameters"/>
</wsdl:message>
<wsdl:message name="getMessageByReferenceRequest">
<wsdl:part element="impl:getMessageByReference" name="parameters"/>
</wsdl:message>
<wsdl:message name="sendRispostaAsincronaSimmetricaRequest">
<wsdl:part element="impl:sendRispostaAsincronaSimmetrica" name="parameters"/>
</wsdl:message>
<wsdl:portType name="IntegrationManager">
<wsdl:operation name="getMessage">
<wsdl:input message="impl:getMessageRequest" name="getMessageRequest"/>
<wsdl:output message="impl:getMessageResponse" name="getMessageResponse"/>
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="deleteMessage">
<wsdl:input message="impl:deleteMessageRequest" name="deleteMessageRequest"/>
<wsdl:output message="impl:deleteMessageResponse" name="deleteMessageResponse"/>
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="getAllMessagesId">
<wsdl:input message="impl:getAllMessagesIdRequest" name="getAllMessagesIdRequest"/>
<wsdl:output
name="getAllMessagesIdResponse"/>
message="impl:getAllMessagesIdResponse"
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
57/73
</wsdl:operation>
<wsdl:operation name="getAllMessagesIdByService">
<wsdl:input
message="impl:getAllMessagesIdByServiceRequest"
name="getAllMessagesIdByServiceRequest"/>
<wsdl:output
message="impl:getAllMessagesIdByServiceResponse"
name="getAllMessagesIdByServiceResponse"/>
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="getNextMessagesId">
<wsdl:input
name="getNextMessagesIdRequest"/>
message="impl:getNextMessagesIdRequest"
<wsdl:output
name="getNextMessagesIdResponse"/>
message="impl:getNextMessagesIdResponse"
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="getNextMessagesIdByService">
<wsdl:input
message="impl:getNextMessagesIdByServiceRequest"
name="getNextMessagesIdByServiceRequest"/>
<wsdl:output
message="impl:getNextMessagesIdByServiceResponse"
name="getNextMessagesIdByServiceResponse"/>
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="getMessageByReference">
<wsdl:input
name="getMessageByReferenceRequest"/>
message="impl:getMessageByReferenceRequest"
<wsdl:output
message="impl:getMessageByReferenceResponse"
name="getMessageByReferenceResponse"/>
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
58/73
<wsdl:operation name="deleteMessageByReference">
<wsdl:input
message="impl:deleteMessageByReferenceRequest"
name="deleteMessageByReferenceRequest"/>
<wsdl:output
message="impl:deleteMessageByReferenceResponse"
name="deleteMessageByReferenceResponse"/>
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="deleteAllMessages">
<wsdl:input
name="deleteAllMessagesRequest"/>
message="impl:deleteAllMessagesRequest"
<wsdl:output
name="deleteAllMessagesResponse"/>
message="impl:deleteAllMessagesResponse"
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="invocaPortaDelegata">
<wsdl:input
name="invocaPortaDelegataRequest"/>
<wsdl:output
name="invocaPortaDelegataResponse"/>
message="impl:invocaPortaDelegataRequest"
message="impl:invocaPortaDelegataResponse"
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="invocaPortaDelegataPerRiferimento">
<wsdl:input
message="impl:invocaPortaDelegataPerRiferimentoRequest"
name="invocaPortaDelegataPerRiferimentoRequest"/>
<wsdl:output
message="impl:invocaPortaDelegataPerRiferimentoResponse"
name="invocaPortaDelegataPerRiferimentoResponse"/>
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="sendRispostaAsincronaSimmetrica">
59/73
<wsdl:input
message="impl:sendRispostaAsincronaSimmetricaRequest"
name="sendRispostaAsincronaSimmetricaRequest"/>
<wsdl:output
message="impl:sendRispostaAsincronaSimmetricaResponse"
name="sendRispostaAsincronaSimmetricaResponse"/>
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
<wsdl:operation name="sendRichiestaStatoAsincronaAsimmetrica">
<wsdl:input
message="impl:sendRichiestaStatoAsincronaAsimmetricaRequest"
name="sendRichiestaStatoAsincronaAsimmetricaRequest"/>
<wsdl:output
message="impl:sendRichiestaStatoAsincronaAsimmetricaResponse"
name="sendRichiestaStatoAsincronaAsimmetricaResponse"/>
<wsdl:fault message="impl:SPCoopException" name="SPCoopException"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="IntegrationManagerSoapBinding" type="impl:IntegrationManager">
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getMessage">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getMessageRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getMessageResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
60/73
</wsdl:operation>
<wsdl:operation name="deleteMessage">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="deleteMessageRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="deleteMessageResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="getAllMessagesId">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getAllMessagesIdRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getAllMessagesIdResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
61/73
<wsdl:operation name="getAllMessagesIdByService">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getAllMessagesIdByServiceRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getAllMessagesIdByServiceResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="getNextMessagesId">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getNextMessagesIdRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getNextMessagesIdResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="getNextMessagesIdByService">
62/73
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getNextMessagesIdByServiceRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getNextMessagesIdByServiceResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="getMessageByReference">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="getMessageByReferenceRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getMessageByReferenceResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="deleteMessageByReference">
<wsdlsoap:operation soapAction=""/>
63/73
<wsdl:input name="deleteMessageByReferenceRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="deleteMessageByReferenceResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="deleteAllMessages">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="deleteAllMessagesRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="deleteAllMessagesResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="invocaPortaDelegata">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="invocaPortaDelegataRequest">
64/73
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="invocaPortaDelegataResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="invocaPortaDelegataPerRiferimento">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="invocaPortaDelegataPerRiferimentoRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="invocaPortaDelegataPerRiferimentoResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="sendRispostaAsincronaSimmetrica">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="sendRispostaAsincronaSimmetricaRequest">
<wsdlsoap:body use="literal"/>
65/73
</wsdl:input>
<wsdl:output name="sendRispostaAsincronaSimmetricaResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="sendRichiestaStatoAsincronaAsimmetrica">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="sendRichiestaStatoAsincronaAsimmetricaRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="sendRichiestaStatoAsincronaAsimmetricaResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="SPCoopException">
<wsdlsoap:fault name="SPCoopException" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="IntegrationManagerService">
<wsdl:port binding="impl:IntegrationManagerSoapBinding" name="IntegrationManager">
<wsdlsoap:address location="http://pdd/cart/IntegrationManager"/>
66/73
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
67/73
68/73
Allegato ’B’: Header SOAP eToscana
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns="http://it.regione.toscana.cart.pdd/eToscana"
targetNamespace="http://it.regione.toscana.cart.pdd/eToscana"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP_ENV="http://schemas.xmlsoap.org/soap/envelope/"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<!-- Contiene le informazioni da scambiare tra SIL e NAL -->
<xsd:element name="eToscana">
<xsd:complexType>
<!-- Filtri -->
<xsd:sequence>
<xsd:element name="Filters" maxOccurs="1" minOccurs="0">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Filter” maxOccurs="unbound"
minOccurs="1">
<xsd:complexType>
<xsd:attribute name="Key" type="xsd:string" use="required"/>
<xsd:attribute name="Value" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
69/73
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<!-- informazioni eGov -->
<xsd:attribute name="SPCoopTipoMittente" type="xsd:string" />
<xsd:attribute name="SPCoopMittente" type="xsd:string" />
<xsd:attribute name="SPCoopTipoDestinatario" type="xsd:string" />
<xsd:attribute name="SPCoopDestinatario" type="xsd:string" />
<xsd:attribute name="SPCoopTipoServizio" type="xsd:string" />
<xsd:attribute name="SPCoopServizio" type="xsd:string" />
<xsd:attribute name="SPCoopAzione" type="xsd:string" />
<xsd:attribute name="SPCoopID" type="xsd:string" />
<xsd:attribute name="SPCoopRiferimentoMessaggio" type="xsd:string" />
<xsd:attribute name="SPCoopCollaborazione" type="xsd:string" />
<!-- informazioni di integrazione -->
<xsd:attribute name="SPCoopIDApplicativo" type="xsd:string" />
<xsd:attribute name="SPCoopServizioApplicativo" type="xsd:string" />
<xsd:attribute name="SPCoopServizioApplicativoDestinatario" type="xsd:string" />
<!-- SOAPHeader Element -->
<!—
<xsd:attribute
ref="SOAP_ENV:actor"
use="required"
fixed="http://it.regione.toscana.cart.pdd/eToscana"/>
70/73
<xsd:attribute ref="SOAP_ENV:mustUnderstand" use="required" fixed="0"/>
-->
</xsd:complexType>
</xsd:element>
</xsd:schema>
71/73
Domande Frequenti
gestione degli allegati
La gestione degli attachment è trasparente rispetto alla Porta di Dominio, essendo l'attachment
parte del messaggio SOAP (in questo caso SOAP with Attachment). Quindi l'attachment può
essere inviato senza ulteriori complicazioni, sia tramite l'uso dell'interfaccia trasparente, che
tramite l'uso del servizio di Integration Manager. Le Porte di Dominio poi si occuperanno di
gestire i manifest così come previsto nella specifica SPCoop.
72/73
73/73