UNIVERSITÀ POLITECNICA DELLE MARCHE FACOLTÀ DI INGEGNERIA Corso di Laurea in Ingegneria Informatica e dell’Automazione Telerefertazione medica su TCP/IP: progetto e realizzazione degli opportuni Web-Service Tesi di laurea di: Marco Induti Correlatori: Relatore: Prof. Prof. Ing. Aldo Franco Dragoni Paolo Puliti Guido Tascini Anno Accademico 2006-2007 SOMMARIO Capitolo 1. Telemedicina 1.1 1.2 1.2.1 1.2.2 1.3 Introduzione………………………………………………………………….. Applicazioni……………………………………………………………………. Vantaggi………………………………………………………………………… Problemi………………………………………………………………………… Stato dell’arte…………………………………………………………………. pag. pag. pag. pag. pag. 6 7 7 8 9 pag. pag. pag. pag. pag. pag. pag. pag. 15 16 18 19 20 22 22 23 pag. pag. pag. pag. pag. pag. pag. pag. 25 32 34 35 37 38 40 42 pag. pag. pag. pag. pag. pag. pag. 46 47 47 47 53 54 57 pag. pag. pag. pag. pag. pag. 61 75 94 98 108 111 Capitolo 2. Progetto JTelemed 2.1 2.2 2.2.1 2.2.2 2.2.3 2.3 2.3.1 2.3.2 Finalità…………………………………………………………………………… Architettura generale.……………………………………………………… Repository……………………………………………………………………… Ente richiedente…………………………………………………………….. Ente refertante.……………………………………………………………… Soluzioni tecniche…………………………………………………………… Middleware Client-Server….…………………………………………….. Messaggi SOAP.……………………………………………………………… Capitolo 3. I Web-Service 3.1 3.2 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.4 L’architettura Client-Server………………………………………………. Introduzione ai Web-Service……………………………………………. Cosa sono i Web-Service e come funzionano.……………………. XML Schema………………………………………………………………….. UDDI…………………………………………………………………………….. WSDL……………………………………………………………………………. SOAP…………………………………………………………………………….. Cenni su Apache Axis……………………………………………………… Capitolo 4. Progettazione del database 4.1 4.2 4.2.1 4.2.2 4.2.3 4.3 4.4 Specifica delle operazioni……………………………………………...... Progettazione concettuale della base di dati……………………… Un primo schema scheletro……………………………………………… Sviluppo delle componenti dello scheletro…………………………. Schema E-R completo…………………………………………………….. Traduzione verso il modello relazionale…………………………….. Codifica SQL…………………………………………………………………… Capitolo 5. Implementazione del progetto JTelemed 5.1 5.2 5.3 5.4 5.5 5.6 Preparazione dell’ambiente di sviluppo……………………………… Servizi offerti dal Web-Service………..……………………………….. Fase di deploy………………………………………………………………… Una possibile e particolare implementazione del client…….…. Axis Attachments……………………………………………………………. Comunicazione Client-Server……………………………………………. SOMMARIO Capitolo 6. Tecnologie software 6.1 6.1.1 6.2 6.2.1 6.2.2 6.3 6.3.1 6.4 6.4.1 6.5 6.5.1 6.5.2 Java Platform…………………………………………………………………. Le Servlet……………………………………………………………………… Service-Oriented Architecture………………………………………….. Web-Services…………………………………………………………………. Protocollo SOAP…………………………………………………………….. Application Server………………………………………………………….. Apache Tomcat……………………………………………………………… Strumenti di sviluppo……………………………………………………… Apache Axis…………………………………………………………………… Database Relazionale……………………………………………………… Oracle…………………………………………………………………………… FreeTOAD……………………………………………………………………… pag. pag. pag. pag. pag. pag. pag. pag. pag. pag. pag. pag. 119 129 133 137 141 156 156 163 163 167 167 173 Capitolo 7. Problematiche e miglioramenti 7.1 7.2 7.3 Il server Linux……………………………………………………………….. pag. 176 Gestioni critiche……………………………………………………………… pag. 180 Un database Open Source: MySQL…………………………………… pag. 182 Capitolo 8. Pubblicazione 8.1 8.2 Il firewall di Linux…………………………………………………………… pag. 187 Il comando iptables………………………………………………………… pag. 189 Bibliografia………………..………………………………………………………………. pag. 193 INTRODUZIONE La tecnologia dei calcolatori elettronici negli ultimi decenni si è evoluta notevolmente, tanto da rendere il computer un elemento quasi indispensabile in tutti gli ambiti della vita quotidiana. Dal lavoro al tempo libero, dai trasporti alle comunicazioni, dal settore industriale al commerciale, l’uso di hardware e software specifici hanno permesso all’uomo di migliorare il proprio stile di vita ed ottimizzare la gestione delle informazioni e dei dati in suo possesso. In tutto il mondo tale evoluzione si è inevitabilmente estesa anche al campo medico, dove velocità, organizzazione e precisione sono fondamentali e, spesso, consentono di salvare vite umane. In questo panorama globale, anche l’Italia sente forte la necessità di ristrutturare l’intero sistema sanitario nazionale spingendosi verso nuove frontiere, e sviluppando un settore innovativo come quello della Telemedicina. La presente tesi di laurea ha come obiettivo la realizzazione del progetto JTelemed, nato dalla collaborazione tra Nbs srl ed Università Politecnica delle Marche. Nella prima fase è stato analizzato il concetto di Telemedicina ed il ruolo da essa attualmente ricoperto, facendo particolare riferimento alle problematiche delle aziende sanitarie locali e realizzando uno stato dell’arte del sistema sanitario nazionale. Tra gli argomenti trattati spicca uno dei settori di maggior interesse, la telerefetazione, per la quale è stata sviluppata un’architettura software “flessibile” e completa per il teleconsulto e la teleassistenza. Particolare attenzione è stata, infine, dedicata alla descrizione dettagliata del progetto JTelemed e del suo funzionamento, soprattutto della sua implementazione dal punto di vista server in un’ottica di un’architettura client-server, non tralasciando comunque tecnologie e paradigmi di comunicazione caratteristici dell’ambiente client. Tale descrizione è stata sviluppata analizzando ogni singolo passo di progettazione, programmazione e sviluppo del progetto e richiamando alcuni dei software utilizzati per la sua realizzazione. 4 CAP. 1 - TELEMEDICINA Introduzione al concetto di telemedicina e stato dell’arte nella sanità italiana. INDICE ARGOMENTI: 1.1 Introduzione 1.2 Applicazioni 1.2.1 Vantaggi 1.2.2 Problemi 1.3 Stato dell’Arte 5 CAP. 1 - TELEMEDICINA 1.1 Introduzione Il concetto di telerefertazione non è un principio a sé stante, ma nasce in un contesto molto più ampio, nasce come un aspetto particolare, come una branchia, della Telemedicina. In questo capitolo affronteremo una breve descrizione della Telemedicina per chiarire di cosa essa si occupa e quali sono i vantaggi legati al suo impiego nel mondo della sanità, nonché alcune delle sue possibili implementazioni a livello applicativo. Una definizione della Telemedicina che ha riscosso un notevole successo è la seguente: “La Telemedicina rappresenta l’erogazione di servizi sanitari, laddove la distanza rappresenti un fattore critico da parte di professionisti nell’assistenza sanitaria che utilizzino tecnologie dell’informazione e della comunicazione per lo scambio di informazioni rilevanti, per la diagnosi, il trattamento e la prevenzione delle patologie e per l’educazione continuativa degli operatori sanitari, nell’interesse del miglioramento della salute e delle comunità assistite”. La Telemedicina utilizza le tecnologie della telecomunicazione per erogare assistenza sanitaria specialistica, spesso a notevoli distanze, con la possibilità di contenere i costi delle prestazioni. Questo avviene in special modo quando l’Assistenza Sanitaria è rivolta ad aree isolate o comunque dove non sia disponibile direttamente la prestazione specialistica del medico. La Telemedicina consente di conseguire notevoli benefici sia per erogatori di assistenza remota, sia naturalmente, per gli utenti dei servizi, siano essi pazienti o operatori sanitari. Fig. 1.1 – Telemedicina come servizio sanitario delocalizzato 6 CAP. 1 - TELEMEDICINA Lo sviluppo e l’applicazione della Telemedicina richiede significativi expertise nei settori delle telecomunicazioni, delle erogazioni dei servizi sanitari e dell’information tecnology and comunications. L’applicazione della Telemedicina ben si presta ad un opera di cooperazione fra i paesi dotati di maggiori tecnologie e quelli ancora in via di sviluppo. 1.2 Applicazioni Il concetto di telemedicina non significa dunque soltanto “medicina praticata a distanza”, ma include tutti quegli aspetti legati all’assistenza sanitaria in senso lato. Una serie di nuovi concetti sono ora riferiti alla telemedicina; due di questi sono ehealth e tele-health (tele-assistenza). La telemedicina teleassistenza può essere applicata in vari modi in tutti i servizi sanitari; può facilitare e razionalizzare la comunicazione e lo scambio di informazioni, tra servizi di primaria assistenza e gli ospedali, tra ospedali diversi, tra ospedali e i laboratori, tra i servizi di riabilitazione e le organizzazioni paramediche. La telemedicina riguarda anche la direzione e l’amministrazione dell’unità sanitarie locali, i pazienti e i loro familiari. 1.2.1 Vantaggi L’avvento dell’informatica medica e la conseguente introduzione di nuove tecnologie nell’ambito sanitario hanno portato e porteranno notevoli vantaggi sia per i pazienti che per il personale medico. L’introduzione della telemedicina permette : Diagnosi e cure più rapide; Minor numero di spostamenti sia del personale medico che dei pazienti; 7 CAP. 1 - TELEMEDICINA Riduzione dei costi per personale, compreso quello di emergenza; Comunicazioni più veloci; Aggiornamento più semplice e rapido delle informazioni riguardanti diagnosi e metodi di cura; Miglior sostegno allo staff medico per la formazione sia teorica che pratica. 1.2.2 Problemi In passato i costi per l’attrezzatura e le telecomunicazioni erano troppo alti da permetterne un’introduzione su larga scala, oggi tuttavia la situazione sotto questo punto di vista è notevolmente migliorata; il vero ostacolo da affrontare è cercare di introdurre metodi che favoriscano l’accettazione e la comprensione da parte del personale interessato, delle applicazioni di telemedicina e teleassistenza nei servizi sanitari. Tuttavia anche quest’ultimo aspetto si sta via via superando, grazie all’impegno dell’azienda sanitaria locale e nazionale per una informatizzazione del personale sanitario attraverso la creazione di corsi di aggiornamento. Bisogna però sottolineare che l’introduzione della telemedicina influenza i tradizionali metodi di lavoro, si vanno a modificare i modelli di cooperazione, si creano nuove figure lavorative e molto spesso sorgono problemi di distribuzione dei costi e di investimenti delle risorse. Alcuni progetti di telemedicina sono partiti proprio da un’analisi preliminare dell’impatto che possono avere nelle procedure ospedaliere, nella ridistribuzione dei compiti e delle risorse. Dato l’impiego di tecnologie avanzate sia come digitalizzazione che come diffusione dell’informazione, quindi nei settori dell’informatica e della telecomunicazione, è necessaria anche la formazione del personale e l’addestramento dello stesso all’utilizzo corretto delle infrastrutture e alla manutenzione di questo nuovi sistemi. A livello internazionale, ad oggi, si registra una mancanza di uniformità sull’applicazione del concetto di telemedicina, dato che vanno a sovrapporsi due differenti sfere di interesse, quella medica e quella ingegneristica; tutto ciò rende difficile la creazione di standard riconosciuti che possano regolamentare tale disciplina. 8 CAP. 1 - TELEMEDICINA Questo rappresenta un limite alla diffusione e all’impiego su larga scala delle soluzioni che in questi anni sono state elaborate. 1.3 Stato dell’arte Oggigiorno i sistemi sanitari mondiali stanno facendo passi da gigante nell’utilizzo massiccio della telemedicina, grazie soprattutto allo sviluppo di nuove tecnologie. In ambito nazionale ogni regione si sta attrezzando allo sviluppo di sistemi di informatica medica. Uno dei principali progetti a livello nazionale è rappresentato da As.ter: un sistema informativo-informatico per la gestione di tutte le attività del territorio sviluppato dalla USL 11 di Empoli. As.Ter integra, con l’ausilio di una piattaforma tecnologica innovativa, tutti gli applicativi ed i database delle attività sanitarie e sociali svolte sul territorio, consentendo la rilevazione dei bisogni complessivi dei cittadini, l’individuazione delle modalità e dei tempi di risposta ai loro bisogni, la rilevazione dei costi; tutto ciò al fine di pianificare e gestire le attività sociosanitarie sul territorio in un ottica manageriale di costi/benefici. Un altro progetto è stato proposto dal servizio sanitario regionale EmiliaRomagna con il nome di SOLE. Esso è finalizzato a realizzare una rete telematica, basata su una serie di hub (centri di archiviazione) e spoke (centri di acquisizione), di collegamento tra i servizi ospedalieri e i servizi territoriali per agevolare la comunicazione tra operatori sanitari e, di conseguenza, agevolare l'erogazione dei servizi con importanti e positive ricadute sulla continuità assistenziale e sulla semplificazione dell’accesso ai servizi per il cittadino. Un’interessante applicazione sviluppata da un’equipe guidata da Ennio Amori, all’interno di questo progetto è “Neurosurgery Teleconsulting”, un servizio di teleconsultazione tra i centri di neurochirurgia collegati attraverso la rete hub&spoke, nella nuova logica distribuita e digitale, in modo da poter trattare ogni trauma e lesione in modo appropriato sfruttando il livello avanzato che ha raggiunto l’IT. Molti sono i progetti pilota che puntano a creare tra i nostri ospedali e centri d’eccellenza un collegamento con i paesi dell’Europa dell’est, che sono da poco entrati 9 CAP. 1 - TELEMEDICINA nella comunità europea, per fornire servizi di teleconsulto e telediagnosi, come per esempio tra Padova o Milano e la Romania. Nello sviluppo di questo tipo di progetti è possibile usufruire anche dei finanziamenti della comunità europea che ovviamente danno maggiore spinta alla ricerca e permettono di pagare la consulenza di software house, esterne alle aziende sanitarie, che possono dare un forte supporto tecnico e far ottenere un prodotto software più completo ed evoluto. In tutto questo panorama di progetti non emerge nessun sistema simile a quello sviluppato in questa tesi, si tratta sempre di servizi ad hoc per applicazioni specifiche, senza una vera ottica di integrazione e supporto globale di servizi sanitari delocalizzati. Avvicinandoci a realtà più vicine a noi, l’ASUR della regione Marche zona 7 ha sviluppato una serie di progetti che riguardano l’ambito medico tra i quali troviamo: 1. Sistema di Teleconsulto ospedale di Osimo con stazioni fisse e stazioni mobili; 2. Assistente Virtuale; 3. Delocalizzazione della refertazione diagnostica. Il Sistema di Teleconsulto è composto da un server e da un client entrambi situati presso l’Ospedale di Osimo e da tre stazioni fisse composte da tre elettrocardiografi. Ogni elettrocardiografo è provvisto di varie uscite esterne, tra cui quattro seriali RS 232, una rete Ethernet per trasmissione e ricezione di tracciati ecg con relativo referto e stampante Archimed 4240 termica formato A4. Inoltre ogni stazione è dotata di memoria interna per l’archiviazione di quaranta ecg (10 secondi 12 derivazioni) fornita di cellulare Gsm Dual Band con interfaccia per elettrocardiografo e cavi di connessione per la trasmissione digitale dell’ecg alla Centrale di Ascolto, funzione di viva voce per comunicare con la Centrale di Ascolto. Il Client è posto nella zona di controllo della Unità di Terapia Critica del Dipartimento di Medicina Interna dove un operatore è costantemente presente durante le ore del giorno e della notte. Le tre stazioni fisse sono al momento situate presso le Unità di degenza mediche del Presidio Ospedaliero di Osimo ed una presso i Poliambulatori di Camerano situati all’interno di una struttura residenziale per anziani con circa 80 degenti. 10 CAP. 1 - TELEMEDICINA La stazione mobile viene al momento affidata agli operatori della Emergenza Urgenza Territoriale che fanno capo al Distretto Ancona Sud. Fig. 1.2 – Applicazione di telemedicina con elettrocardiografo L’Assistente Virtuale è un progetto, già in parte sviluppato e funzionante, che ha come obiettivo quello di creare un assistente personale virtuale che sia in grado di offrire ad ogni singolo utente un valido appoggio. Si possono connettere a questo sistema tre tipi di client: l’assisto che potrà consultare i propri dati clinici oltre che avere in modo automatico un promemoria degli eventuali esami da svolgere o dei referti pronti alla consultazione, un motore di ricerca personalizzato e potenziato e un forum. Gli altri due utenti, il medico di base e il medico specialista, sono tuttavia ancora in fase di realizzazione. Gli utenti avranno a disposizione un alter-ego virtuale che attraverso un’interfaccia user-friendly sarà in grado di rispondere attraverso una voce sintetica alle domande scritte dagli utenti stessi, quindi un sistema con interfaccia amichevole per accedere ai propri dati clinici che funga anche da archivio e agenda sanitaria. 11 CAP. 1 - TELEMEDICINA Per quanto riguarda invece la Delocalizzazione della Refertazione Diagnostica, nell’ottica di capillarizzare l’offerta sanitaria così come negli obiettivi della sanità regionale, può essere importante pensare ad una struttura informatica che renda indipendenti le due fasi della diagnostica: l’esecuzione dell’esame e la sua refertazione. Infatti mentre è possibile pensare di localizzare alcuni macchinari (di basso costo) anche nei poliambulatori più piccoli, può risultare sconveniente portare in questi poliambulatori personale di alta specializzazione. Quello che ci si propone è di potenziare la rete di acquisizione dell’esame digitale, aumentando il numero delle macchine e dei tecnici di laboratorio, concentrando invece il personale medico che deve compilare il referto; il personale di laboratorio ha un costo inferiore rispetto ai dottori, quindi si aumentano capacità, capillarità e efficienza del servizio limitando gli investimenti. La struttura informatica che ci si propone di realizzare in questa fase, poi potrà anche servire per altri scopi come consulti medici oppure per fornire servizi (a pagamento) di refertazione per altri enti. L’architettura di massima proposta è quindi la seguente: Fig. 1.4 – Schema a blocchi delocalizzazione diagnostica 12 CAP. 1 - TELEMEDICINA Sostanzialmente un sistema per la refertazione a distanza altro non è che un repository di eventi sanitari con relativo output dell’esame (per esempio radiografia, elettrocardiogramma, etc). In questo repository gli enti periferici (poliambulatori, etc.) depositano gli output degli esami e prelevano i referti mentre il centro di refertazione preleva gli output degli esami ed inserisce i referti relativi. Per mettere in piedi la procedura appena descritta è indispensabile che tutti i partecipanti siano collegati, attraverso una infrastruttura PKI funzionante, ad una rete intranet o internet utilizzando un metodo di trasferimento sicuro (SSL). Il progetto Jtelemed nasce proprio come ricerca di una soluzione ingegneristica a livello software per rispondere ad un’esigenza sanitaria di delocalizzazione. Requisiti fondamentali di tale sistema, data la varietà di dati da trattare e di ambienti in cui operare, sono la semplicità e la flessibilità; tenendo presenti questi due punti il sistema può raggiungere un livello di efficienza adeguato al supporto di servizi di teleconsulto e la telerefertazione e non solo, in generale per qualsiasi servizio sanitario delocalizzato. 13 CAP. 2 – PROGETTO JTELEMED Descrizione dell’architettura del Progetto JTelemed, spiegazione del funzionamento delle varie componenti del sistema: repository, richiedente e refertante. Panoramica delle soluzioni tecniche adottate. INDICE ARGOMENTI: 2.1 Finalità 2.2 Architettura generale 2.2.1 Repository 2.2.2 Ente richiedente 2.2.3 Ente refertante 2.3 Soluzioni tecniche 2.3.1 Middleware Client-Server 2.3.2 Messaggi SOAP 14 CAP. 2 – PROGETTO JTELEMED 2.1 Finalità Il progetto JTelemed nasce dalla collaborazione tra l’Università Politecnica delle Marche e l’N.b.s s.r.l, come soluzione software, all’esigenza di poter delocalizzare la refertazione diagnostica. L’obiettivo del progetto è quello di fornire, un prodotto flessibile che implementasse un servizio di refertazione asincrono, cioè in grado di separare non solo da un punto di vista temporale, ma anche da quello spaziale, l’esecuzione dell’esame dalla refertazione dello stesso. Per asincrono intendiamo che non ci si aspetta che l’esame venga refertato in tempo reale, ma in un tempo accettabile concordato tra i fornitori del servizio e gli utenti. Fig. 2.1 – Contesto del progetto La figura mostra che la nostra architettura fornisce un supporto per lo sviluppo di servizi sanitari, ovvero non si pone l’obiettivo di sostituire i sistemi informativi già esistenti che sono molteplici e variegati, ma li vuole integrare in una rete di comunicazione sicura che faciliti e razionalizzi lo scambio di informazioni. Nello specifico si tratta di servizi di teleconsulto in ambiente Intranet e/o Internet, quindi basati su TCP/IP, come la refertazione e la “second opinion”. 15 CAP. 2 – PROGETTO JTELEMED Visto che l’ambiente in cui opera il nostro sistema è intrinsecamente non sicuro, uno dei requisiti fondamentali da rispettare è il livello di sicurezza e di affidabilità, del trattamento del dato clinico, cioè consentire uno scambio di informazioni sicuro in un ambiente,internet, che non lo è per definizione. Lo scopo di JTelemed è creare un’applicazione software completa in grado di gestire l’intero processo di telerefertazione, più in generale supportare in modo sicuro un servizio sanitario delocalizzato. 2.2 Architettura generale Il primo passo fatto per progettare JTelemed (il nome è ottenuto dall’unione delle parole Java e Telemedicina) è stato capire come si doveva integrare con il sistema informativo sanitario già esistente; la prima ipotesi semplificativa adottata è stata quella di creare una piattaforma flessibile per lo sviluppo di servizi sanitari. Si è pensato di creare una struttura semplice, basata su standard diffusi e riconosciuti in modo da sviluppare una piattaforma che potesse facilmente essere applicata in ambito sanitario sia a livello del personale medico che in un prossimo futuro direttamente ai cittadini. JTelemed si basa sul concetto di evento: questo aspetto rappresenta il punto focale dell’intero sistema. L’effettuazione di un esame presso una qualsiasi struttura clinica e la conseguente archiviazione del dato in forma digitale genera ciò che viene chiamato evento. L’evento non è il dato clinico vero e proprio ma rappresenta una sorta di metadato-clinico del dato digitale generato dai laboratori. E’ composto da una serie di informazioni che riguardano il dato digitale prodotto dall’evento come ad esempio: l’unità che ha erogato la prestazione, la data e l’ora dell’esame, la struttura che l’ha prodotto, il dottore richiedente ed il codice dell’impegnativa, lo stato della fase di refertazione, e, cosa molto importante il link che consente di scaricare il dato. Ogni evento quindi viene immagazzinato all’interno di un apposito raccoglitore, definito repository, che costituisce il nucleo del sistema e che funziona da collegamento tra colui che referta e l’esame. 16 CAP. 2 – PROGETTO JTELEMED Questo legame è contenuto nell’evento e il repository è una sorta di sofisticato gestore di eventi clinici. Qualsiasi esame che può essere memorizzato in forma digitale può essere associato ad un evento, con questa soluzione ingegneristica si è riusciti ad ottenere quella flessibilità ed adattabilità che venivano richieste in fase di progettazione. Una soluzione semplice, ma molto efficace, che è il cardine fondamentale dei progetti di sistemi informativi in ambito sanitario. L’architettura, di conseguenza, mostra un’analoga flessibilità e semplicità, infatti è prevista la presenza solamente di tre attori principali che interagiscono tra loro e che rappresentano un’astrazione delle funzioni principali: da un lato l’esecuzione dell’esame, dall’altro la generazione del referto, con al centro un nodo di gestione del sistema. Fig. 2.2 – Architettura generale dell’applicativo JTelemed Il cuore del sistema è rappresentato dal Repository centrale, che altro non è che un server relazionale, cioè un server che gestisce un DataBase. Il Repository può essere ospitato da un azienda o da un ente erogante, il quale si impegna a certificare l’identità di coloro che usufruiscono del servizio (medici e laboratori) e a garantire il corretto funzionamento e la manutenzione dell’intero sistema. 17 CAP. 2 – PROGETTO JTELEMED Nella parte destra della figura sono rappresentate le strutture che producono i dati digitali di un esame clinico e che si interfacciano nel sistema come dei client di laboratorio: sono quelli che attivano il processo di refertazione e attendono i risultati. Dall’altra parte si trova il personale che fornisce il servizio di refertazione, una clinica specializzata, un semplice medico o una equipe di medici; attraverso l’interfaccia del medico possono interagire nel nostro sistema e pubblicare il proprio referto autenticandolo con la propria firma. Oltre alla figura del Repository possiamo dunque identificare le altre due entità fondamentali che costituiscono il nostro sistema: ENTE RICHIEDENTE ENTE REFERTANTE Vediamo brevemente in cosa consistono queste entità. 2.2.1 Repository La struttura del sistema prevede la presenza di un repository centrale, costituito da un server che ospita un database relazionale nel quale vengono memorizzati le informazioni relative ai dati digitali prodotti nei laboratori. Ogni registrazione all’interno del database di questo repository costituisce quello che noi chiamiamo “evento”; l’evento rappresenta una sorta di meta-dato informativo riguardante il dato digitale prodotto nei laboratori. Le informazioni che vengono registrate sono data e ora dell’inserimento nella base dati, il tipo di esame eseguito, informazioni sulla provenienza della richiesta di prestazione sanitaria, l’esame o meglio il dato digitale riguardante l’esame vero e proprio e alcune informazioni personali dei pazienti, quali età, peso, altezza che sono di fondamentale importanza per la fase di diagnosi. Da notare che non vengono mai registrate le informazioni anagrafiche del paziente: infatti il primo obiettivo è quello di fornire un servizio di refertazione che abbia la possibilità di concedere “second opinion”. 18 CAP. 2 – PROGETTO JTELEMED Tutto ciò rende molto flessibile la struttura eliminando i problemi riguardanti la privacy. Nel caso di applicazioni future per telediagnosi, o per la consultazione della cartella clinica dei pazienti, avremmo l’obbligo legale di strutturare in modo più robusto, dal punto di vista della sicurezza, il server che ospita il repository, oltre all’utilizzo di tecniche di criptazione per la memorizzazione dei dati. 2.2.2 Ente richiedente La seconda figura che viene presa in esame è l’utente (o ente) richiedente; con questo termine si indica una qualsiasi entità che abbia la necessità di farsi refertare un esame; potrebbe essere un laboratorio radiologico, analisi, epidemiologico oppure un autoambulanza con apposita apparecchiatura, una piattaforma petrolifera (anche essa con la giusta strumentazione), un medico di base che chiede opinioni ad un medico specialistico, un infermiere ecc…. Quindi nella descrizione del sistema si parlerà sempre di richiedente come interfaccia comune che identifica in modo univoco ognuna di queste unità. L’ente richiedente crea un nuovo evento, cioè una volta effettuato un esame e ottenuto il dato digitale sia in maniera diretta o tramite passaggi di discretizzazione, entra nel portale web con username e password e tramite un opportuna interfaccia inserisce i dati relativi all’esame eseguito all’interno del database centrale. Grazie al repository che pubblica l’evento, il dato digitale presente nel laboratorio diventa accessibile e pronto per essere refertato da parte degli altri attori di questo sistema, i dottori o meglio il personale specializzato per la refertazione. Una volta generato l’evento il richiedente può monitorare l’evento, ossia controllare tutte le varie fasi di refertazione che l’evento da lui generato subisce, fino a che non ritiene soddisfatta la sua richiesta. A questo punto dichiara chiuso l’evento e termina la fase di refertazione; ovviamente solo chi ha generato la richiesta può dichiarare terminato il processo di refertazione: infatti ogni utente richiedente potrà visionare solo gli eventi da lui stesso creati. 19 CAP. 2 – PROGETTO JTELEMED Fig. 2.3 – Funzionalità lato del laboratorio. 2.2.3 Ente refertante Una volta che un utente richiedente apre un evento e quindi va ad aggiungere un record al Repository centrale, effettua una richiesta di refertazione all’altra figura che compare nell’architettura di JTelemed: l’ente refertante costituito da un insieme di medici, o per non generalizzare, da un insieme di personale specializzato. Ogni utente refertante effettuando l’accesso tramite un semplice web browser (per esempio Internet Explorer o Mozilla) accede al sistema dove tramite opportune interfacce user-friendly vengono mostrati tutti gli eventi che il medico è in grado di refertare: questo perché uno degli scopi del presente lavoro è quello di creare un portale per servizi di “second-opinion”. Inoltre ognuno di essi potrà visualizzare un elenco di tutti gli eventi che può refertare, dove sono presenti data e ora di inserimento nel database, lo stato dell’esame (aperto, refertato, chiuso) e infine il link per effettuare il download sul proprio pc del dato clinico per visualizzarlo in modalità offline e quindi refertarlo in modo asincrono. 20 CAP. 2 – PROGETTO JTELEMED Fig. 2.4 – Funzionalità lato refertante. Quando un medico decide di refertare un esame, gli verrà presentata una form dove può effettuare l’upload del suo referto che deve essere scritto e salvato in un file di qualsiasi formato, ad esempio testo (*.txt). In questo modo si viene a creare il meccanismo di “second opinion” (uno degli obiettivi di partenza del progetto). Inoltre egli può anche dichiarare il referto appena inviato al repository centrale non definitivo, cioè può riservarsi il privilegio di inviare un referto non ancora completo, ovviamente prendendosi l’onere di completarlo in breve tempo. Il sistema provvederà a memorizzare nel database la data e l’ora della refertazione, garantendo quindi in modo inequivocabile l’istante temporale in cui il dottore ha effettuato il referto. L’attendibilità del medico che può effettuare referti è verificata in fase di accesso da parte del medico al browser dal sistema attraverso un’identificazione con username e password. In questo modo si offrono le garanzie necessarie alla fase di refertazione. 21 CAP. 2 – PROGETTO JTELEMED 2.3 Soluzioni tecniche JTelemed è un applicazione “object-oriented” basata su internet che fa uso di un database relazionale per memorizzare i dati. L’architettura prescelta è quella delineata da Java 2 Enterprise Edition della Sun e gli strumenti di sviluppo sono: Eclipse 3.2.0 WTPAll-in-one, JDK 1.5.0 e Apache Tomcat 5.5 – come piattaforma di sviluppo; Classi Java – per la realizzazione della parte server; SitePainter e PortalStudio – per le interfacce web lato client (non verranno approfondite) Apache Axis – per la realizzazione del web service; I database supportati sono tutti quelli con interfacce JDBC, in questo caso Oracle, ma senza particolare sforzo potrà, in futuro, essere estesa ad altri tipi di database, di tipo free, come ad esempio MySQL. I client possono accedere in qualsiasi momento per consultazione o inserimento dati utilizzando un comune Web Browser. Ogni operatore accederà a funzionalità diverse del sistema sulla base del proprio profilo professionale certificato dall’amministratore del sistema stesso: ciò significa che solo chi è stato autenticato come personale autorizzato potrà entrare, attraverso la pagina del login, nel portale web e usufruire dei suoi servizi. 2.3.1 Middleware Client-Server JTelemed è un middleware client-server cioè un una piattaforma software che è interposta tra l'utente finale e il database. Esso è composto da un server web relazionale scritto in Java e quindi perfettamente adattabile a qualsiasi piattaforma grazie all’impiego della Java Virtual Machine e da un unico client sia per l’utente refertante che per il richiedente. 22 CAP. 2 – PROGETTO JTELEMED Il client si collega al sistema direttamente tramite web browser, senza necessità di avere installato componenti particolari, come per esempio la virtual machine stessa che risiede solo sul server: infatti sono il PortalStudio e il Tomcat che traducono il codice Java lato server e lo trasformano in codice HTML per il client. Il requisito della compatibilità è fondamentale specialmente in ambiente remoto che può essere il più vario possibile. 2.3.2 Messaggi SOAP La comunicazione all’interno del sistema, avviene con scambio di messaggi SOAP (cosa sono e come funzionano verrà spiegato nei prossimi capitoli). I dati si inviano come allegati ai messaggi SOAP, è stata scelta questa tecnica per lo scambio di informazione perché avendo come obbiettivo quello di creare una struttura in grado di adattarsi a qualsiasi tipo di esame, era importante avere la possibilità di scambiare messaggi di dimensioni variabili, in questo modo abbiamo raggiunto tale obbiettivo. Ad esempio, un dato proveniente da un laboratorio radiologico produce dei file Dicom di dimensioni che si aggirano attorno ai 30 Mb (dipende dall’esame), con questo sistema non si sono verificati problemi di trasmissione dei pacchetti. Una cosa importante da notare è che per implementare questa struttura si ha bisogno di una rete a larga banda che consenta le transizioni di file di dimensione variabile. 23 CAP. 3 – I WEB-SERVICE Prima di procedere con la descrizione dell’implementazione del progetto JTelemed occorre avere una panoramica essenziale su alcune delle tecnologie software su cui si basa il progetto stesso, tecnologie e nozioni fondamentali per una comprensione più efficace delle varie fasi di realizzazione. In particolare verrà introdotto un concetto cardine del mondo del web: il Web-Service. Alcune terminologie e gli altri strumenti software verranno poi approfonditi e descritti in seguito nei prossimi capitoli. INDICE ARGOMENTI: 3.1 L’architettura Client-Server 3.2 Introduzione ai Web-Service 3.3 Cosa sono i Web-Service e come funzionano 3.3.1 XML Schema 3.3.2 UDDI 3.3.3 WSDL 3.3.4 SOAP 3.4 Cenni su Apache Axis 24 CAP. 3 – I WEB-SERVICE 3.1 Architettura Client-Server Il modello Client-Server è il paradigma di Distributed Computing che allo stato attuale viene utilizzato maggiormente. Tale modello permette a processi situati su differenti calcolatori di cooperare in tempo reale attraverso lo scambio di messaggi, ottenendo così un notevole miglioramento rispetto, ad esempio, al modello File- Transfer, che richiede il trasferimento di interi file e in cui le computazioni sui dati sono eseguite off-line. Il modello Client/Server viene tipicamente implementato attraverso le chiamate di procedura remota (RPC), che estende lo scopo di una chiamata locale, oppure attraverso il paradigma degli oggetti distribuiti che estende lo scopo del modello degli oggetti locali. Il modello di calcolo Client/Server nasce con l’obiettivo di poter utilizzare più efficacemente le possibilità offerte dalla distribuzione delle risorse di quanto non fosse ottenibile impiegando il modello File sharing. Infatti le limitazioni che questo schema impone sono piuttosto stringenti e non permettono un proficuo uso delle capacità della distribuzione, imponendo di fatto la coesistenza di un limitato numero di processi nel sistema. Le caratteristiche del modello Client/Server, tra le quali la struttura modulare e l’utilizzo dello scambio di messaggi nella cooperazione tra processi, permette al contrario di ottenere buone prestazioni per quel che riguarda requisiti importanti quali l’utilizzabilità, la flessibilità, l’interoperabilità, e la scalabilità. Fig. 3.1 - Relazione tra i modelli di calcolo 25 CAP. 3 – I WEB-SERVICE Innanzitutto è opportuno chiarire che, in questo ambito, quando si parla di modello Client/Server, ci si riferisce ad un’architettura software, vale a dire ad uno schema dove esistono processi che forniscono servizi (server) e processi che usufruiscono dei servizi (client), ciò però, non è necessariamente legato al fatto che i due tipi di processi siano bipartiti su macchine distinte, una detta Client e l’altra Server. Questa precisazione è importante poiché in generale si tende a considerare Client la macchina sulla quale si lavora, e Server la macchina alla quale ci si può collegare per usufruire di un servizio. Purtroppo la coincidenza dei nomi può generare confusione. Tipicamente molte applicazioni possono essere logicamente viste come se composte da tre componenti. Nella prima componente troviamo l’interfaccia verso l’utente, cioè tutti quei meccanismi che si occupano di manipolare gli input dalla tastiera, dal mouse e dai vari dispositivi d’ingresso, nonché di fornire l’output verso l’utente. Nella seconda troviamo l’applicazione in senso più stretto, vale a dire quell’insieme di funzionalità, specifiche del problema da risolvere. L’insieme di tali funzionalità viene tipicamente riferito con il nome di “business logic”. Infine la terza componente fornisce alle altre due quei servizi generali necessari e che si riferiscono, ad esempio, alla comunicazione ed alla gestione dei dati. In un’architettura Client/Server le componenti logiche di cui si è parlato possono essere poste su due o tre differenti strati. Ciò porta a distinguere due diverse forme di architettura Client/Server: two-tier Client/Server architecture; three-tier Client/Server architecture; Nei due sottoparagrafi che seguono verranno brevemente illustrate queste due differenti architetture ed al fine di rendere il discorso più concreto ci si riferirà, come esempio, ad una applicazione che richiede servizi per la gestione di dati (database service). 26 CAP. 3 – I WEB-SERVICE Two-tier Client/Server architecture In uno schema two-tier le tre componenti vengono implementate su due differenti strati. Nel primo strato vengono poste le funzionalità relative all’interfaccia ed una parte di quelle relative alla “business logic”, mentre nel secondo strato sono poste le funzionalità di servizio (nel nostro esempio le funzioni di gestione della base di dati) e quelle rimanenti della “business logic”. I due strati corrispondono rispettivamente ad un processo Client e ad un processo Server che comunicano tra di loro; il primo richiedendo servizi e l’altro fornendo i servizi corrispondenti. Tipicamente la comunicazione viene realizzata attraverso l’invocazione di procedure remote (RPC) oppure, nel caso di “database server”, attraverso il linguaggio SQL. Nel nostro esempio il costrutto SQL è inviato al processo Server che esegue nel suo ambiente le computazioni corrispondenti e restituisce al Client i risultati della richiesta. La comunicazione tra il Client ed il Server richiederà dunque il trasferimento dei soli dati rilevanti per la query risparmiando evidentemente banda rispetto al modello file sharing che avrebbe richiesto il trasferimento di più file. Three-tier Client/Server architecture Lo schema three-tier si sviluppa come evoluzione dello schema two-tier poiché quest’ultimo risulta inadeguato per la soluzione di alcuni problemi complessi, ed inoltre presenta alcuni inefficenze riguardanti ad esempio la scalabilità, l’interoperabilità e la portabilità. Secondo il modello three-tier le tre componenti della struttura logica di un’applicazione vengono implementate da altrettanti strati. La realizzazione dell’applicazione risulta allora più complessa ma permette di rimediare alle caratteristiche negative dell’architettura two-tier. Per illustrare, con un esempio, questo tipo di architettura, consideriamo un sistema in cui siano presenti più database server e supponiamo di dover eseguire una transazione che richieda l’accesso a dati residenti su server distinti. Come è noto le caratteristiche di una transazione, che devono essere garantite da un sistema che permetta l’esecuzione di tali operazioni su basi di dati, sono: atomicità, serializzabilità e persistenza. 27 CAP. 3 – I WEB-SERVICE L’utilizzo di un’architettura di tipo two-tier, si rivela in questo caso inefficente, richiedendo una complessa coordinazione (sarebbe questa la parte della business logic presente nel server) delle basi di dati presenti. Infatti, ogni database server prevede supporti soltanto per l’esecuzione di transazioni che interessino esclusivamente dati locali. La soluzione del problema passa attraverso l’introduzione di un terzo strato che contenga tutta la business logic e si occupi di coordinare le diverse basi di dati. Questo strato intermedio è riferito in letteratura con il nome di Transaction Processing monitor. I vantaggi più evidenti portati da una tale soluzione sono l’affrancamento del Client dalle caratteristiche dei singoli database server e la realizzazione di una architettura software in cui la modularità risulta enfatizzata. Riassumendo possiamo dire che il modello Client-Server è “un modello di interazione tra una coppia di processi uno dei quali richiede un servizio (Client) ad un altro che lo fornisce (Server)”. Fig. 3.2 – Il modello Client/Server nel World Wide Web I Client e i Server sono dei moduli funzionali con interfacce ben definite (le informazioni interne sono invisibili all’esterno). Le funzioni possono essere realizzate da moduli hardware, software o da una combinazione dei due e l’interazione ClientServer (C/S) si attiva tra due moduli funzionali quando uno di essi (Client) richiede un servizio e un altro (Server) decide di rispondere alla richiesta. 28 CAP. 3 – I WEB-SERVICE Durante un’interazione i ruoli del Client e del Server rimangono immutati, mentre possono variare per interazioni diverse. Lo scambio di informazioni tra i moduli avviene attraverso messaggi (non attraverso l’uso di variabili globali) ed il messaggio scambiato è una “capsula” all’interno della quale vengono inseriti i dati oggetto della comunicazione e che viene inviato al modulo corrispondente. I messaggi scambiati sono tipicamente interattivi e generano l’attivazione di processi all’interno dei moduli (eseguiti on-line). Esistono tuttavia rare eccezioni, come i sistemi di gestione dei messaggi (posta elettronica), nei quali il server memorizza i messaggi in una coda e li recupera in modo asincrono successivamente per inoltrarli. Il World Wide Web introduce una nuova dimensione nell’architettura delle applicazioni C/S: le interfacce utente sono sostituite dai Web Browsers (Clients) che accedono direttamente ai documenti HTML gestiti dai Web Servers o da altre applicazioni attrvarso i Gateways. Fig. 3.3 – Il modello Client/Server nel World Wide Web (W3) 29 CAP. 3 – I WEB-SERVICE Un server W3 può: Fornire pagine statiche: Alla richiesta di un client, che specifica tramite un URL il documento a cui è interessato, recupera il file corrispondente e lo invia al richiedente. Fig. 3.4 – Server come fornitore di servizi statici Fornire pagine dinamiche: In questo caso il server crea dinamicamente la pagina in base alle richieste del client e la invia al richiedente. Esistono vari strumenti per la realizzazione di questa funzione, quali ad esempio PHP, CGI, Java Servlets Fig. 3.5 – Server come fornitore di servizi dinamici 30 CAP. 3 – I WEB-SERVICE Il client più diffuso nel W3 è invece un browser che tramite un’interfaccia grafica permette di visualizzare i documenti contenuti nei siti W3. Essi sono costituiti da un nucleo software principale che implementa le funzioni di base (interazione http, interpretazione codice HTML, XML, JavaScript, esecuzione di programmi Java…). Chiarita cosa sia un architettura C/S e i ruoli che svolgono il client e il server all’interno di questa architettura è possibile fare un passo in avanti e introdurre il concetto di Web-Service. 31 CAP. 3 – I WEB-SERVICE 3.2 Introduzione al Web-Service Il paradigma del Service Oriented Computing è visto come una rivoluzione nella comunità informatica e i Web services una sua realizzazione. La possibilità di vedere il Web come un grande sistema informativo in cui sono forniti innumerevoli servizi offre agli utenti finali un potentissimo strumento che va al di là del vero scambio di informazioni che al momento rappresenta il Web. I servizi web, meglio noti come Web services, sono diventanti uno degli argomenti più attuali nel panorama dello sviluppo in ambiente Internet. Posti al centro delle più recenti strategie di aziende del calibro di IBM, Microsoft e Sun, vengono spesso descritti come una vera e propria rivoluzione nel mondo del Web ed in particolare per tutto quanto attiene allo sviluppo di applicazioni distribuite ed all'integrazione di applicazioni. Focalizzando l’attenzione sul concetto di servizio è ovvio immaginare, anche alla luce di quanto detto finora, come gli attori in causa siano necessariamente il fornitore e il richiedente. Questo tipo di paradigma è il medesimo che si riscontra nella tipica interazione di tipo Client-Server. Attraverso la SOA (Service-Oriented Architecture) questa interazione viene arricchita con un ulteriore attore detto Service Directory o Service Broker che, come mostrato in figura 3.6, si inserisce all’interno della comunicazione tra fornitore e fruitore del servizio. Fig. 3.6 – Service Oriented Architecture 32 CAP. 3 – I WEB-SERVICE Service Provider Chi realizza e mette a disposizione un servizio. Tramite l’operazione di publish il servizio viene “pubblicizzato”, in quanto le caratteristiche del servizio realizzato vengono memorizzate all’interno di un registry accessibile pubblicamente. Il Service Provider rimane, quindi, in attesa che un utente richieda tale servizio. Service Directory o Service Broker Questo componente si occupa della gestione del registry, permettendo, a chi ha necessità, di ricercare un servizio sulla base delle caratteristiche con le quali è stato definito e memorizzato. Naturalmente, il Service Directory può seguire politiche di controllo degli accessi sulle interrogazioni in modo da limitare la visibilità sui servizi inseriti. Nel presente lavoro il registry, viene considerato parzialmente accessibile. Service Requestor Rappresenta un potenziale utente che richiede un servizio. A tale scopo, tramite la primitiva di find l’utente interagisce con il Service Directory per ottenere il servizio più adatto ai propri obiettivi. Una volta individuato si collega al Service Provider corrispondente (bind) e inizia a fruire del particolare servizio (use). Partendo da questa considerazione si può dire che una architettura per e- Service è un’istanza di una SOA dove il mezzo di comunicazione è di tipo elettronico, mentre una architettura per Web service è un’istanza di una SOA dove il mezzo di comunicazione considerato è il Web. 33 CAP. 3 – I WEB-SERVICE 3.3 Cosa sono i Web services e come funzionano Un Web-Service è un componente applicativo. Possiamo definirlo come un sistema software in grado di mettersi al servizio di un applicazione comunicando su di una medesima rete tramite il protocollo HTTP. Un Web-Service consente quindi alle applicazioni che vi si collegano di usufruire delle funzioni che mette a disposizione. Esso comunica tramite protocolli e standard definiti "aperti" e quindi sempre a disposizione degli sviluppatori ed ha una caratteristica molto particolare ed utile al suo scopo: è auto-contenuto ed autodescrittivo, cioè è in grado di farci sapere che funzioni mette a disposizione (senza bisogno di conoscerle a priori) e ci permette inoltre di capire come vanno utilizzate. Il protocollo HTTP si occupa di mettere in comunicazione il servizio web con l'applicazione che intende usufruire delle sue funzioni. Oltre ad HTTP però, i servizi web utilizzano molti altri standard web, tutti basati su XML, tra cui: • XML Schema • UDDI (Universal Description, Discovery and Integration) • WSDL (Web Services Description Language) • SOAP (Simple Object Access Protocol) È importante sottolineare che XML può essere utilizzato correttamente tra piattaforme differenti (Linux, Windows, Mac) e differenti linguaggi di programmazione. XML è inoltre in grado di esprimere messaggi e funzioni anche molto complesse e garantisce che tutti i dati scambiati possano essere utilizzati ad entrambi i capi della connessione. Si può quindi dire che i Web services sono basati su XML ed HTTP e che possono essere utilizzati su ogni piattaforma e con ogni tipo di software. 34 CAP. 3 – I WEB-SERVICE 3.3.1 XML Schema Abbiamo detto che un Web service è auto-descrittivo. Con XML Schema cominceremo a capire come fa un servizio web a disporre di questa caratteristica. XML Schema serve per definire qual è la costruzione legale di un documento XML, come fanno per esempio i DTD con le pagine web. Vediamo una lista delle principali funzioni di XML Schema: • Definire gli elementi (tag) che possono apparire in un documento; • Definire gli attributi che possono apparire in un elemento; • Definire quali elementi devono essere inseriti in altri elementi (child); • Definire il numero degli elementi child; • Definire quando un elemento deve essere vuoto o può contenere testo, elementi, oppure entrambi; • Definire il tipo per ogni elemento e per gli attributi (intero, stringa, ecc, ma anche tipi personalizzati); • Definire i valori di default o fissi per elementi ed attributi; Ecco un esempio di XML Schema in grado di descriverlo: <?xml version="1.0"?> <!-- iniziamo lo schema --> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.XXXX.it/Guida_ai_Webservice" xmlns="http://www.XXXX.it/Guida_ai_Webservice" elementFormDefault="qualified"> <!-- definiamo l'elemento libro --> <xs:element name="libro"> <xs:complexType> <xs:all> <!-- definiamo i vari elementi child di libro --> <xs:element name="titolo" type="xs:string" /> <xs:element name="autore" type="xs:string" /> <xs:element name="numeroDiPagine" type="xs:integer" /> </xs:all> </xs:complexType> </xs:element> </xs:schema> 35 CAP. 3 – I WEB-SERVICE Per ora concentriamoci sul primo elemento: schema. Questo è l'elemento che racchiude tutti i tipi di dato che andiamo a descrivere. Il tag <schema> può avere diversi attributi. • xmlns:xs="..." stabilisce che gli elementi che iniziano con 'xs' provengono dal namespace http://www.w3.org/2001/XMLSchema . • targetNamespace="..." definisce a quale namespace appartengono gli elementi definiti con questo schema . • xmlns="..." definisce il namespace di default (quello applicato se non ne escplicitiamo uno) • elementFromDefault="qualified" indica che ogni elemento usato nel documento XML che utilizzerà questo schema dovrà essere qualificato. Una volta aperto il tag <schema> bisogna inserire al suo interno tutti gli elementi che vogliamo definire per il nostro documento. Esistono sostanzialmente due tipi di elementi: • gli elementi semplici non possono contenere altri elementi e avere attributi. Possono contenere solo testo. • gli elementi complessi possono contenere testo, altri elementi e attributi in qualsiasi combinazione. 36 CAP. 3 – I WEB-SERVICE 3.3.2 UDDI L'UDDI (acronimo di Universal Description Discovery and Integration) è un registry (ovvero una base dati ordinata ed indicizzata), basato su XML ed indipendente dalla piattaforma hardware, che permette alle aziende la pubblicazione dei propri dati e dei servizi offerti su internet. L ‘UDDI permette quindi la scoperta e l'interrogazione dei servizi offerti sul web, delle aziende che li offrono e della maniera per usufruirne. Una "registrazione" UDDI consiste, infatti, di tre diverse componenti: • Pagine bianche (White Pages): indirizzo, contatti (dell'azienda che offre uno o più servizi) e identificativi; • Pagine gialle (Yellow Pages): categorizzazione dei servizi basata su tassonomie standardizzate; • Pagine verdi (Green Pages): informazioni (tecniche) dei servizi fornite dall'azienda L'UDDI è uno degli standard alla base del funzionamento dei Web services: è stato progettato per essere interrogato da messaggi in SOAP e per fornire il collegamento ai documenti WSDL che descrivono i vincoli protocollari ed i formati dei messaggi necessari per l'interazione con i Web services elencati nella propria directory. 37 CAP. 3 – I WEB-SERVICE 3.3.3 WSDL Il WSDL serve a specificare dove si trovano i servizi e le operazioni esposte dal servizio web. Cominciamo subito a vedere come un documento WSDL definisce un Web service. All'interno del documento esistono quattro elementi principali: • <types> • <message> • <portType> • <binding> <definitions> <types> <!-- definizione dei tipi di dato utilizzati... --> </types> <message> <!-- definizione di uno dei messaggi impiegati dal web service per comunicare con l'applicazione client --> </message> <!-- naturalmente può esistere più di un elemento message all'interno del documento --> <portType> <!-- definisce una "porta" e le operazioni che possono essere eseguite dal web service. Definisce inoltre i messaggi coinvolti nelle operazioni elencate --> </portType> <binding> <!-- definisce il formato del messaggio ed i dettagli di protocollo per ogni porta --> </binding> </definitions> 38 CAP. 3 – I WEB-SERVICE I types, message e portType sono elementi del messaggio WSDL all’interno di definitions e sono usati per definire le operazioni: • <types> è usato per definire i tipi base necessari allo scambio dell’informazione. • <message> è usato per definire il messaggio spedito e ricevuto ed utilizza i tipi definiti in types. • <portTypes> è usato per definire il funzionamento delle porte allocate dal servizio come i messaggi da utilizzare in input e output. Gli elementi binding e service sono usati per definire il protocollo associato all’operazione: • <binding> è usato per definire il protocollo da utilizzare per comunicare con la porta su cui è allocata l’operazione (HTTP, SOAP,…). • <service> è usato per definire una porta come URL attraverso la quale si trova il servizio. Il WSDL inoltre definisce quattro tipi di operazioni attraverso il tag <operations>: – One-way: è una chiamata asincrona al servizio. – Request-responce: chiamata sincrona al servizio. – Sollicit-responce: invia una risposta dopo un sollecito. – Notification: ricevere una notifica. 39 CAP. 3 – I WEB-SERVICE 3.3.4 SOAP E’ utile sapere che tutte le informazioni che vengono definite da WSDL, è grazie a SOAP (Simple Object Access Protocol) se vengono scambiate tra il Web service è l'applicazione che vi accede. Questo protocollo fornisce una via per comunicare tra applicazioni eseguite su sistemi operativi diversi, con diverse tecnologie e linguaggi di programmazione, tramite HTTP ed XML. Un messaggio SOAP è un documento XML che contiene i seguenti elementi: • Envelope, identifica il documento come un messaggio SOAP; • Un elemento Header opzionale, contenete informazioni specifiche per l'applicazione, che non sarà approfondito in questa sede ma che permette di definire alcuni messaggi, anche con diversi destinatari nel caso il messaggio dovesse attraversare più punti di arrivo; • Body è un elemento indispensabile che contiene le informazioni scambiate dalle richieste/risposte; • Fault è un elemento opzionale che fornisce informazioni riguardo ad eventuali errori manifestati durante la lettura del messaggio. Le regole principali per realizzare un messaggio SOAP sono le seguenti: • Deve essere ovviamente codificato con XML • Deve utilizzare il SOAP Evenelope namespace Encoding namespace (http://www.w3.org/2001/12/soap-envelope) • Deve utilizzare il SOAP (http://www.w3.org/2001/12/soap-encoding) • Non deve contenere il collegamento ad un DTD e non deve contenere istruzioni per processare XML Lo "scheletro" di un messaggio SOAP: 40 CAP. 3 – I WEB-SERVICE <?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope (http://www.w3.org/2001/12/soap-envelope)" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <soap:Header> ... </soap:Header> <soap:Body> ... <soap:Fault> ... </soap:Fault> </soap:Body> </soap:Envelope> All'interno dell'elemento Envelope abbiamo definito i namespace soap evelope ed encoding che come abbiamo visto sono richiesti per questo tipo di documento. Se non vengono definiti o si definiscono diversamente le applicazioni coinvolte nella comunicazione potrebbero generare un errore o scartare il messaggio. 41 CAP. 3 – I WEB-SERVICE 3.4 Apache Axis Axis è il motore opensource più famoso per la creazione di Web services in Java. Axis è un progetto dell'Apache Software Fondation e deriva da SOAP4J, un progetto regalato dall'IBM ad Apache. Brevemente, si tratta di un’API di programmazione e deployment di Web services che permette di lavorare ad un livello di astrazione elevato, evitando così di dover maneggiare direttamente l’envelope SOAP. Con Axis è possibile, dunque, implementare Web services e anche sviluppare client di servizi di terzi. Per semplicità, viene esposto solo l’aspetto di funzionalità RPC e non quello relativo ai vari approcci di messaging supportati da Axis. Ciò è comunque in linea con la maggior parte della casistica Web services che si basa su meccanismi request/response a dispetto del modello asincrono. Axis 1.4 disponibile all’URL http://ws.apache.org/axis/ è composto da: • una web application che si occupa di gestire l'ambiente di esecuzione dei servizi (routing, istance pooling, serializzazione e deserializzazione dei messaggi SOAP, ecc...); • una API composta da classi di utilità per la scrittura di servizi web e da classi necessarie al funzionamento della web application e dei tool; • una serie di tool, tra cui WSDL2Java per generare scheletri lato server e stub lato client dei servizi web a partire dalla descrizione WSDL; • Java2WSDL per generare la descrizione come servizio web di una classe Java; • diversi tool per l'amministrazione e la gestione dei servizi installati; • un TCP monitor stand-alone ed un SOAP monitor integrato nella web application per controllare la forma dei messaggi scambiati tra i servizi nelle fasi di debug e test. Tra le caratteristiche più interessanti di Axis c'è la possibilità di creare Web service in maniera immediata a partire da classi Java molto semplici con estensione .jws (Java Web Service). 42 CAP. 3 – I WEB-SERVICE Axis può essere quindi utilizzato in una serie di scenari anche molto diversi tra loro, ad esempio può servire per: • la creazione di applicazioni client di servizi web già esistenti per i quali è disponibile il WSDL: utilizzando WSDL2Java si possono creare in maniera automatica gli stub per l'accesso a servizi esistenti implementati con qualsiasi piattaforma. Le applicazioni client che utilizzano gli stub non necessitano di ambienti di esecuzione particolari ma soltanto della presenza della libreria axis.jar nel proprio classpath; • la comunicazione via JAX-RPC tra processi Java: le API di Axis implementano una versione di JAX-RPC, rendendo possibile lo sviluppo di applicazioni distribuite Java con protocollo di trasporto SOAP; • la creazione di servizi web a partire da classi Java: Axis offre diversi meccanismi per l'implementazione dei servizi. Quello più semplice e completamente trasparente per il programmatore è JWS, ma sono disponibili anche modelli di servizi più complicati dove è possibile personalizzare, ad esempio, le modalità di serializzazione dei messaggi, la struttura dei package ed il formato dei parametri, senza mai occuparsi della descrizione WSDL o del formato SOAP dei messaggi, grazie all'integrazione tra l'ambiente di esecuzione e Java2WSDL; • l'implementazione di servizi web a partire da descrizioni WSDL: il tool WSDL2Java è particolarmente utile quando, come nel caso di Zlatan, si parte dalla descrizione dei servizi per la realizzazione di un sistema piuttosto che dalla loro implementazione. I problemi principali di Axis riguardano lo stretto legame con il web application container Tomcat (anche se è possibile con qualche sforzo installare l'ambiente in altri server, come fatto con SJSAS8 in Zlatan) e la conformità soltanto parziale alle specifiche del WS-I. 43 CAP. 3 – I WEB-SERVICE Riassumendo possiamo dire che Axis non è che un SOAP engine: questo significa che è un framework che si concentra unicamente sulle problematiche della creazione di client e server e per la gestione di messaggi SOAP; in pratica consiste in un insieme di tool per la generazione automatica di classi e in una libreria che “incapsula” in classi Java l’accesso alle tecnologie connesse ai Web-Service. L’architettura generale di Axis appare nella seguente figura nei suoi componenti principali: Fig. 3.7- Architettura generale di Axis. Il requestor è un client che effettua una richiesta su alcuni dei protocolli supportati da Axis. Generalmente è usato HTTP. Il requestor può essere una desktop application, una web application, o un altro web service. Il motore Axis agisce agevolando la comunicazione tra client e web service maneggiando la traduzione ad e da web service standard. Axis permette allo sviluppatore di definire una serie di handlers, allacciati alla richiesta o alla risposta. Questi handlers sono simili a filtri servlet; ogni handler svolge uno specifico compito adando avanti fino al prossimo handler in linea. 44 CAP. 4 – PROGETTAZIONE DEL DATABASE Un ultimo passo prima di descrivere la realizzazione del progetto: progettazione fisica del database. Specifica delle operazioni, progettazione concettuale della base di dati, schema di progettazione e script per la creazione del database. INDICE ARGOMENTI: 4.1 Specifica delle operazioni 4.2 Progettazione concettuale 4.2.1 Un primo schema scheletro 4.2.2 Sviluppo delle componenti dello scheletro 4.2.3 Schema E-R completo 4.3 Traduzione verso il modello relazionale 4.4 Codifica SQL 45 CAP. 4 – PROGETTAZIONE DEL DATABASE 4.1 Specifica delle operazioni Il modello base impostato ha come concetti di riferimento l’Utente Richiedente, oggetto del servizio di assistenza e l’Utente Erogante, soggetti che erogano il servizio di refertazione. Il richiedente (accreditato) che si interfaccia con questo applicativo deve avere la possibilità di fare una richiesta “generica” (senza un destinatario definito) pubblicando il risultato di una indagine clinica. A questo punto un qualunque refertante accreditato può interagire con il nostro applicativo e fornire una risposta al richiedente. Se il richiedente è soddisfatto della refertazione ottenuta può chiudere il processo di pubblicazione, altrimenti lasciare pubblicata la richiesta in attesa di refertazione da parte di refertanti diversi. Fig. 4.1 – Architettura del progetto JTelemed. 46 CAP. 4 – PROGETTAZIONE DEL DATABASE 4.2 Progettazione concettuale Per quanto riguarda la Progettazione Concettuale del nostro DataBase, abbiamo seguito una strategia mista come andremo a descrivere. 4.2.1 Un primo schema scheletro (top-down) Sono state identificate inizialmente le seguenti entità (che hanno vita propria e indipendente l’una delle altre): Utente Richiedente e Utente Refertante. Ad un primo livello di astrazione è concepito il seguente schema scheletro: 4.2.2 Sviluppo delle componenti dello scheletro (inside-out) Sia l’Utente Richiedente che l’Utente Refertante appartengono a delle strutture cliniche accreditate e si differenziano tra di loro solo per il ruolo che ricoprono nell’interfacciarsi con l’applicativo. Si può pensare, quindi, di accorpare queste due entità in una sola entità e sfruttare una relazione ricorsiva. Ogni UTENTE è caratterizzato da: • un identificativo univoco dell’utente all’interno del sistema, ID; • un CommonName che deve essere presente anche all’interno del certificato digitale, CN; • un tipo di utente (R= utente richiedente, E= utente erogante), TYPE; • un codice identificativo dell’utente, CODENTE; 47 CAP. 4 – PROGETTAZIONE DEL DATABASE • un codice identificativo della struttura, CODSTRUTTURA; • un codice della specialità della struttura, CODSPECIALITA; • un codice identificativo dell’unità erogante, CODUNITAEROGANTE; • una username dell’utente per l’accesso al Repository, USERNAME; • una password dell’utente per l’accesso al Repository, PASSWORD. La chiave primaria per questa entità è l’ID (univoco). Un utente richiedente può emettere una o più richieste di refertazione [cardinalità (1,N)], mentre un utente erogante può rispondere alle richieste di nessuno o più richiedenti [cardinalità (0,N)]. Ogni utente (richiedente o refertante) appartiene ad una UNITA’ EROGANTE che è caratterizzata da: • un identificativo dell’ente, CODENTE; • un identificativo della struttura, CODSTRUTTURA; • un identificativo della specialità, CODSPECIALITA; • un codice dell’unità erogante, CODUNITAEROGANTE; • una descrizione dell’unità erogante, DESCR; Le chiavi primarie sono: CODENTE, CODSTRUTTURA, CODSPECIALITA e CODUNITAEROGANTE. 48 CAP. 4 – PROGETTAZIONE DEL DATABASE A questo punto, è possibile definire un’entità TIPO ESAME che permetterà di tener traccia di tutte le possibili patologie. Ogni patologia è individuata da: • un codice identificativo della patologia dell’esame, CODICE; • una descrizione della patologia dell’esame, DESCR. Ogni laboratorio accreditato che richiede una refertazione ad un altro laboratorio genera un EVENTO. Le informazioni necessarie per un qualsiasi evento risultano essere: • identificativo univoco dell’evento all’interno del sistema, ID; • identificativo univoco del richiedente, UTN_ID; • tipologia dell’esame collegato all’evento, TRF_CODICE; • data e ora di creazione dell’evento, DATE_OPEN; • data e ora di chiusura dell’evento, DATE_CLOSE; • il file allegato all’evento, ALLEGATO; • nome del file allegato, NOMEALLEGATO; • codice di ricerca esterna, CODICE_ESTERNO; • dati aggiuntivi del paziente quali RAZZA, SESSO, ETA, ALTEZZA, UM_ALTEZZA, PESO, UM_PESO, MEMO. 49 CAP. 4 – PROGETTAZIONE DEL DATABASE Un utente può generare uno o più eventi (richiesta di refertazione) mentre un evento è legato ad uno ed un solo utente [cardinalità: (1,N) ; (1,1)]. Ad ogni evento, invece, è associata un’unica patologia. Il richiedente deve essere un utente accreditato e quindi già registrato nella tabella UTENTI: per questo motivo UTN_ID è chiave esterna con l’ ID della tabella UTENTI. La tipologia di esame deve essere una di quelle previste dalla tabella TIPO_ESAMI, perciò TRF_CODICE è chiave esterna con il CODICE della tabella TIPO_ESAMI. dateclose Quando un utente refertante fornisce una risposta ad un utente richiedente genera un REFERTO. Le informazioni necessarie per un qualsiasi referto risultano essere: • indice progressivo del referto dell’evento, IND; • identificativo univoco dell’evento all’interno del sistema, EVT_ID; • identificativo dell’utente che ha scritto il referto, UTN_ID; • file che contiene il referto in formato testo, ALLEGATO_REFERTO; • nome del file del referto, NOMEALLEGATO_REFERTO; • data e ora di inserimento del referto, DATEREFERTO. 50 CAP. 4 – PROGETTAZIONE DEL DATABASE Un referto è la risposta ad un determinato evento: perciò EVT_ID è chiave esterna con l’ID dell’evento. L’utente che ha effettuato il referto deve essere un ente accreditato e già registrato nella tabella UTENTI: per questo motivo UTN_ID è chiave esterna con l’ID della tabella UTENTI. Si noti che ad un evento possono essere associati più referti (in generale potranno essere forniti referti ad un evento finché l’evento non viene chiuso). Ogni utente refertante potrà eseguire refertazioni solo ed esclusivamente sulle patologie di competenza, ovvero solo per le patologie a lui accreditate; per questo motivo si inserisce un’entità PERMISSIONI. Tale entità è composta da due campi: • identificatore dell’utente, IDUTE (chiave primaria e chiave esterna con ID della tabella UTENTI); • identificatore della patologia di competenza, CODESAME. 51 CAP. 4 – PROGETTAZIONE DEL DATABASE 52 CAP. 4 – PROGETTAZIONE DEL DATABASE 4.2.3 Schema E-R completo dateclose CAP. 4 – PROGETTAZIONE DEL DATABASE 4.3 Traduzione verso il modello relazionale Tabella TM_UTENTI Nome del campo Tipo Dim. Identificat. Chiave esterna UTN_ID (Autonumber) Number 10 UTN_CN Varchar 128 UTN_TYPE Varchar 1 UTN_CODENTE Varchar 10 TM_UNITAEROGANTI. UER_CODENTE UTN_CODSTRUTTURA Varchar 10 TM_UNITAEROGANTI. UER_CODSTRUTTURA UTN_CODSPECIALITA Varchar 10 UTN_CODUNITAEROGANTE Varchar 10 UTN_USERNAME Varchar 20 UTN_PASSWORD Varchar 20 Primary Key TM_UNITAEROGANTI. UER_CODSPECIALITA TM_UNITAEROGANTI. UER_CODUNITAEROGA NTE Tabella TM_ UNITAEROGANTI Nome del campo Tipo Dim. Identificatore Varchar 10 Primary Key UER_CODSTRUTTURA Varchar 10 Primary Key UER_CODSPECIALITA Varchar 10 Primary Key UER_CODUNITAEROGANTE Varchar 10 Primary Key UER_DESC Varchar 50 UER_CODENTE Chiave esterna 54 CAP. 4 – PROGETTAZIONE DEL DATABASE Tabella TM_TIPOESAMI Nome del campo TES_CODICE TES_DESCR Tipo Dim. Identificatore Varchar 10 Primary Key Varchar 255 Chiave esterna Tabella TM_EVENTI Nome del campo Tipo Dim. Identificatore Chiave esterna EVT_ID (Autonumber) Number 10 Primary Key EVT_UTN_ID Number 10 TM_UTENTI.UTN_ID EVT_TRF_CODICE Varchar 10 TM_TIPOESAMI.TES_CODICE EVT_DATEOPEN Date EVT_DATECLOSE Date EVT_ALLEGATO Blob EVT_NOMEALLEGATO Varchar 25 EVT_CODICE_ESTERNO Varchar 10 EVT_RAZZA Varchar 25 EVT_SESSO Varchar 1 EVT_ETA Number 3 EVT_ALTEZZA Number (8,4) EVT_UM_ALTEZZA Varchar 10 EVT_PESO Number (8,4) EVT_UM_PESO Varchar 10 EVT_MEMO Varchar 255 55 CAP. 4 – PROGETTAZIONE DEL DATABASE Tabella TM_REFERTI Nome del campo Tipo Dim. Identificatore Chiave esterna REF_IND (Autonumber) Number 10 Primary Key REF_EVT_ID Number 10 TM_EVENTI.EVT_ID REF_UTN_ID Number 10 TM_UTENTI.UTN_ID REF_ALLEGATO_REFERTO Blob REF_NOMEALLEGATO_REFERT O Varchar REF_DATEREFERTO Date REF_MEMO Varchar REF_DEFINITIVO Char 25 255 1 Tabella TM_PERMISSIONI Nome del campo Tipo Dim. Identificatore Chiave esterna PER_UTN_ID Number 10 Primary Key TM_UTENTI.UTN_ID PER_TES_CODICE Varchar 10 Primary Key TM_TIPOESAMI.TES_CODICE 56 CAP. 4 – PROGETTAZIONE DEL DATABASE 4.4 Codifica SQL CREATE TABLE TM_UNITAEROGANTI ( uer_codente VARCHAR(10) DEFAULT '' NOT NULL, uer_codstruttura VARCHAR(10) DEFAULT '' NOT NULL, uer_codspecialita VARCHAR(10) DEFAULT '' NOT NULL, uer_codunitaerogante VARCHAR(10) DEFAULT '' NOT NULL, uer_descr VARCHAR(50) DEFAULT NULL, PRIMARY KEY (uer_codente,uer_codstruttura,uer_codspecialita,uer_codunitaerogan te) ); CREATE TABLE TM_TIPOESAMI ( tes_codice VARCHAR(10) DEFAULT '', tes_descr VARCHAR(255) DEFAULT '' NOT NULL, PRIMARY KEY (tes_codice) ); CREATE TABLE tm_utenti ( utn_id NUMBER(10) PRIMARY KEY, utn_cn VARCHAR(128) DEFAULT NULL UNIQUE, utn_type VARCHAR(1) DEFAULT 'M' NOT NULL, utn_codente VARCHAR(10) DEFAULT NULL, utn_codstruttura VARCHAR(10) DEFAULT NULL, utn_codspecialita VARCHAR(10) DEFAULT NULL, utn_codunitaerogante VARCHAR(10) DEFAULT NULL, utn_username VARCHAR(20), utn_password VARCHAR(20), FOREIGN KEY (utn_codente, utn_codstruttura, utn_codspecialita, utn_codunitaerogante) REFERENCES TM_UNITAEROGANTI(UER_CODENTE, UER_CODSTRUTTURA, UER_CODSPECIALITA, UER_CODUNITAEROGANTE) ); CREATE SEQUENCE TM_UTENTI_SEQ START WITH 1 INCREMENT BY 1 NOMAXVALUE; 57 CAP. 4 – PROGETTAZIONE DEL DATABASE CREATE TRIGGER TM_UTENTI_TRIGGER BEFORE INSERT ON TM_UTENTI FOR EACH ROW BEGIN SELECT TM_UTENTI_SEQ.NEXTVAL INTO :NEW.UTN_ID FROM DUAL; END; CREATE TABLE tm_eventi ( evt_id NUMBER(10) NOT NULL, evt_utn_id NUMBER(10) DEFAULT NULL, evt_trf_codice VARCHAR(10) DEFAULT NULL, evt_dateopen DATE DEFAULT NULL, evt_dateclose DATE DEFAULT NULL, evt_allegato BLOB, evt_nomeallegato VARCHAR(25) DEFAULT '--', evt_codice_esterno VARCHAR(10) DEFAULT '--', evt_razza VARCHAR(25) DEFAULT '--', evt_sesso VARCHAR(1) DEFAULT '--', evt_eta NUMBER(3) DEFAULT 0, evt_altezza NUMBER(8,4), evt_um_altezza VARCHAR(10), evt_peso NUMBER(8,4), evt_um_peso VARCHAR(10), evt_memo VARCHAR(255) DEFAULT '-', PRIMARY KEY (evt_id), FOREIGN KEY (evt_trf_codice) REFERENCES TM_TIPOESAMI(tes_codice), FOREIGN KEY (evt_utn_id) REFERENCES TM_UTENTI(utn_id) ); CREATE SEQUENCE TM_EVENTI_SEQ START WITH 1 INCREMENT BY 1 NOMAXVALUE; CREATE TRIGGER TM_EVENTI_TRIGGER BEFORE INSERT ON TM_EVENTI FOR EACH ROW BEGIN SELECT TM_EVENTI_SEQ.NEXTVAL INTO :NEW.EVT_ID FROM DUAL; END; 58 CAP. 4 – PROGETTAZIONE DEL DATABASE CREATE TABLE tm_referti ( ref_ind NUMBER(10) NOT NULL, ref_evt_id NUMBER(10) DEFAULT '0' NOT NULL, ref_utn_id NUMBER(10) DEFAULT '0' NOT NULL, ref_allegato_referto BLOB, ref_nomeallegato_referto VARCHAR(25), ref_datereferto DATE, PRIMARY KEY (ref_ind), FOREIGN KEY (ref_evt_id) REFERENCES TM_EVENTI (evt_id), FOREIGN KEY (ref_utn_id) REFERENCES TM_UTENTI (utn_id) ); CREATE SEQUENCE TM_REFERTI_SEQ START WITH 1 INCREMENT BY 1 NOMAXVALUE; CREATE TRIGGER TM_REFERTI_TRIGGER BEFORE INSERT ON TM_REFERTI FOR EACH ROW BEGIN SELECT TM_REFERTI_SEQ.NEXTVAL INTO :NEW.REF_IND FROM DUAL; END; CREATE TABLE TM_PERMISSIONI ( per_utn_id NUMBER(10) DEFAULT '0' NOT NULL, per_tes_codice VARCHAR(10) DEFAULT '' NOT NULL, PRIMARY KEY (per_utn_id, per_tes_codice), FOREIGN KEY (per_utn_id) REFERENCES TM_UTENTI(utn_id), FOREIGN KEY (per_tes_codice) REFERENCES TM_TIPOESAMI (tes_codice) ); 59 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Descrizione dell’ambiente con cui è stato sviluppato il Web-Service e dei servizi da esso messi a disposizione. Dettagli su aspetto critico della comunicazione Client-Server: gli attachments. INDICE ARGOMENTI: 5.1 Preparazione dell’ambiente di sviluppo 5.3 Servizi offerti dal Web-Service 5.2 Fase di deploy 5.4 Una possibile e particolare implementazione del client 5.5 Attachments 5.6 Comunicazione Client-Server 60 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED 5.1 Preparazione dell’ambiente di sviluppo Per la creazione dell’ambiente di sviluppo si è proceduto come segue: • Installazione della JDK 1.5 e della JRE 1.5 mediante l’utilizzo del kit J2SE Development Kit 5.0; in tal modo si è creata la cartella C/Programmi/Java contenente le sottodirectory jdk1.5.0 e jre1.5.0.; • Installazione dell’Application Server JAKARTA TOMCAT (vedremo più avanti cosa sia) attraverso l’eseguibile jakarta-tomcat-5.5.4.exe; nella fase di installazione, per prima cosa, è stata selezionata l’opzione per l’aggiunta del componente opzionale Webapps ed infine si è selezionato Destination cartella per come folder la C:/TOMCAT554; verificare l’effettivo funzionamento del Tomcat si è visualizzata la home page del medesimo attraverso l’URL http://localhost:8080; • Come IDE di sviluppo è stato scelto Eclipse: la versione a cui faremo riferimento è la WTP 1.5 AllInOne. Tale sigla sta per Web Tools Project, e contiene, fra l'altro, Eclipse 3.2. In questa versione ci sono già molte funzionalità rivolte al Web, come suggerisce il nome. L'installazione è semplicissima, anzi, non necessita neanche di una installazione. Una volta scaricato il file compresso è sufficiente scompattarlo ed Eclipse è già pronto. La prima volta che avviamo Eclipse viene chiesta la directory dove salvare i nostri progetti. Una volta scelta, ci troveremo di fronte all'ambiente grafico di sviluppo. 61 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED • Istallazione di APACHE AXIS che consiste nei due seguenti passi: Fig. 5.1 - Cartella scompattata di Axis. 1) Scompattare Axis, prendere la cartella lib e copiarla all'interno della installazione di Eclipse. 2) Prendere la cartella axis dentro webapps e incollarla sull'omonima cartella di Tomcat. A questo punto abbiamo tutti gli strumenti necessari per creare il nostro Web service, ma prima di iniziare vediamo la disposizione delle varie librerie: • per un corretto funzionamento dell’applicativo lato server sono necessarie le seguenti librerie nella directory della JDK (nel nostro caso versione 1.5) C:/Programmi/Java/jdk1.5.0/jre/lib/ext.: dnsns.jar sunjce_provider.jar localedata.jar sunpkcs11.ja 62 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED • • le librerie necessarie sotto C:/TOMCAT554/common/lib sono: activation.jar mail.jar commons-el.jar naming-factory-dbcp.jar jasper-compiler jdt.jar naming-factory.jar jasper-compiler.jar naming-resources.jar jasper-runtime.jar ojdbc14.jar jsp-api.jar servlet-api.jar le librerie necessarie sotto C:/TOMCAT554/webapps/axis/WEB-INF/lib sono: activation.jar jaxrpc.jar axis-ant.jar log4j-1.2.8.jar axis.jar mail.jar commons-discovery-0.2.jar saaj.jar commons-logging-1.0.4.jar wsdl4j-1.5.1.jar Chiarite le posizioni delle varie librerie cominciamo a costruire il nostro Web service a partire dalla IDE di sviluppo Eclipse: • Innanzitutto selezionare dalla toolbar la voce File->New->Project (figura 5.2). Nella successiva finestra indicare il tipo di progetto che si vuole realizzare, nel nostro caso un Dinamic Web Project (figura 5.3). 63 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Fig. 5.2 – Creazione del Web Service Il primo passo per la costruzione di un Web-Service è rappresentato dalla scelta del tipo di progetto tra quelli che l’IDE Eclipse mette a disposizione. Nella figura successiva si può notare che esistono varie tipologie di progetti, una delle quali dedicata al mondo del Web. 64 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Fig. 5.3 – Creazione del Web service Non è difficile riconoscere quale sia effettivamente il tipo di progetto da selezionare per la creazione di un web service: aprire la directory Web e selezionare la voce Dynamic Web Project • Successivamente verrà chiesto di dare un nome al nuovo progetto e di lavorare con delle impostazioni. Per il nostro scopo è possibile utilizzare le impostazioni di default e una volta completata la procedura l’interfaccia di eclipse appare nel seguente modo (figura 5.4): 65 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Figura 5.4 - L’interfaccia di Eclipse • Come ultimo passo non rimane altro che testare il prototipo di applicazione costruito; per fare ciò basta lanciare l’applicazione stessa all’interno di Eclipse attraverso il comando Run. Poiché abbiamo però costruito una web application, occorre definire il server su cui far girare il progetto: Eclipse a questo scopo ci permette di impostare una sorta di server interno che si appoggia all’Application Server istallato sulla macchina di sviluppo, nel nostro caso JAKARTA TOMCAT. Vediamo brevemente come funziona il tutto. Con il tasto destro del mouse cliccare sull’icona del progetto che appare nella Resource Navigator view e scegliere Run As -> Run On Server (figura 5.5). 66 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Successivamente selezionare dall’elenco messo a disposizione il server desiderato, in questo caso Apache Tomcat v.5.5 (figura 5.6). Anche in questo caso è possibile modificare delle impostazioni, ma non è controidicativo utilizzare quelle di default. Concludendo tale procedimento guidato l’istallazione del nostro server interno è completata e l’applicazione Fig. 5.5 – Impostare il server di Eclipse (1) è pronta per essere utilizzata (figura 5.7). Figura 5.6 Impostare il server di Eclipse (2). E’ necessario selezionare dall’elenco di figura lo stesso Application Server che si è istallato sulla macchina di lavoro. Come sempre facciamo riferimento a questo caso che utilizza un Tomcat versione 5.5 67 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Fig. 5.7 – Impostare il server di Eclipse (3) Come ulteriore verifica della funzionalità del server possiamo utilizzare la Console: Figura 5.8 – La Console di Eclipse Come vedremo più avanti Eclipse mette inoltre a disposizione un ulteriore strumento di controllo in fase di utilizzo dei servizi, il TCP/IP Monitor. 68 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED • Ora tutto il nostro sistema è funzionante, ma prima di ultimare il lavoro occorre fare un piccolo passo indietro. Conclusa la fase di editing con la creazione delle classi che implementano i servizi occorre costruire il descrittore dei servizi, il WSDL. Ricordiamo che il WSDL serve a specificare dove si trovano i servizi e le operazioni esposte dal servizio web. L’Eclipse mette a disposizione un meccanismo rapido ed efficiente per la creazione automatica di tale descrittore che fisicamente non è altro che un file xml. Cliccare con il tasto destro del mouse sulla classe nella quale sono definiti i servizi che il nostro progetto vuole realizzare. Selezionando la voce Web Service -> Create Web Service (figura 5.9) si apre una finestra di impostazioni (figura 5.10): “spuntare” le due voci Publish the Web service e Monitor the Web service; inoltre se è necessario il TCP/IP Monitor Fig. 5.9 – Generazione del WSDL (1) spostare la completamente barra in (1) alto. Successivamente apparirà un’ulteriore finestra nella quale è possibile selezionare tutti i servizi da inserire nel wsdl e scegliere il cosiddetto “Style and use” impostandolo a RPC/Encoded. Questa caratteristica rappresenta la scelta del formato di un messaggio SOAP. 69 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Le possibili scelte di SOAP:Body di un messaggio SOAP sono: - document: il SOAP Body del documento contiene una o più "parts" che dal punto di vista di XML sono childNodes di SOAP:Body. Non ci sono particolari regole sulla struttura di questi nodi figli. - RPC: il SOAP:Body contiene un elemento il cui nome corrisponde al nome della procedura remota da invocare e un elemento per ogni parametro da fornire alla procedura. La serializzazione del SOAP:Body prevede: - encoded: le regole di serializzazione sono dettate dalla sezione 5 della specifica SOAP 1.1 . - literal: i dati sono serializzati nel rispetto di una specifica XML che ad oggi è XML Schema Definition 1.0, domani potrebbe essere altro. In .NET tutto questo si trasforma nell'utilizzare, come decorazione dei nostri WebMethod, uno dei due seguenti attributi: - SoapRpcMethod: il SOAP:Body sarà RPC/encoded. - SoapDocumentMethod: SOAP:Body in formato document. Se la proprietà Use vale SoapBindingUse.Literal il body sarà document/literal, se invece Use vale SoapBindingUse.Encoded avremo un body document/encoded. Se la proprietà ParameterStyle vale SoapParameterStyle.Bare avremo i parametri inviati tra i SOAP Node posizionati direttamente all'interno del SOAP:Body. Se invece la proprietà ParameterStyle vale SoapParameterStyle.Wrapped i parametri saranno inviati tra i due SOAP node, racchiusi all'interno di un solo elemento, figlio di SOAP:Body. Il default di ASP.NET è Literal, Wrapped. 70 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Barra (1). Spostare la barra completamente in alto per avere il TCP/IP Monitor Opzioni da selezionare Figura 5.10. Generazione del WSDL (2) Risultato di tutta questa procedura è un file .wsdl di cui riportiamo un piccolo frammento: INTESTAZIONE <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://services.jtelemed.it" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://services.jtelemed.it" xmlns:intf="http://services.jtelemed.it" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <!--WSDL created by Apache Axis version: 1.3 Built on Oct 05, 2005 (05:23:37 EDT)--> 71 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED DEFINIZIONE DEI METODI <wsdl:message name="openeventResponse"> <wsdl:part name="openeventReturn" type="xsd:int"/> </wsdl:message> <wsdl:message name="userinfoResponse"> <wsdl:part name="userinfoReturn" type="xsd:string"/> </wsdl:message> <wsdl:message name="listeventsResponse"> <wsdl:part name="listeventsReturn" type="xsd:string"/> </wsdl:message> PORT TYPE <wsdl:portType name="WSRepository"> <wsdl:operation name="echo" parameterOrder="value"> <wsdl:input message="impl:echoRequest" name="echoRequest"/> <wsdl:output message="impl:echoResponse" name="echoResponse"/> </wsdl:operation> <wsdl:operation name="userinfo" parameterOrder="utn_cn username password"> <wsdl:input message="impl:userinfoRequest" name="userinfoRequest"/> <wsdl:output message="impl:userinfoResponse" name="userinfoResponse"/> </wsdl:operation> 72 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED BINDING <wsdl:binding name="WSRepositorySoapBinding" type="impl:WSRepository"> <wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="echo"> <wsdlsoap:operation soapAction=""/> <wsdl:input name="echoRequest"> <wsdlsoap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ namespace="http://services.jtelemed.it" use="encoded"/> </wsdl:input> <wsdl:output name="echoResponse"> <wsdlsoap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ namespace="http://services.jtelemed.it" use="encoded"/> </wsdl:output> </wsdl:operation> SERVIZI <wsdl:service name="WSRepositoryService"> <wsdl:port binding="impl:WSRepositorySoapBinding" name="WSRepository"> <wsdlsoap:address location="http://localhost:8080/jtelemed/services/WSRepository"/> </wsdl:port> </wsdl:service> Infine per testare l’effettivo funzionamento del Web-Service occorre creare un client che si interfacci con i servizi messi a disposizione. Anche in questo caso l’Eclipse ha una via veloce ed efficiente: riprendendo lo schema di figura 5.9, basta selezionare Generate Sample JSPs. 73 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Nel Resource Navigator view di Eclipse apparirà una nuova directory: Lanciando l’applicazione server appare sul una Directory Listing For sampleWSRepository dove WSRepository è la classe con la quale è costruito il Web service. La lista è composta da quatto link ai file .jsp evidenziati in figura. Selezionando “TestClient.jsp” si accede alla fase di testing dei servizi. Fig. 5.11 – Creazione del client di test 74 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED 5.2 Servizi offerti dal Web-Service Come ormai più volte detto, un Web-Service è un’entità in grado di soddisfare delle richieste da parte di un generico client, ovvero uno strumento software che mette a disposizione dei suoi utilizzatori determinati servizi. Dunque descrivere l’implementazione del Web-Service significa descrivere i servizi da esso messi a disposizione, i meccanismi per invocare tali servizi e il criterio di elaborazione e produzione dei risultati. La struttura è molto semplice: WSRepository Application DateTime FileUtil String Util wsApp WSRepository() echo(…) userinfo(…) listevents(…) openEvent(….) closeEvent(…) downloadEvent(…) referta(…) listEventsReferted(…) listEventsRefertedByEvtId(…) downloadRefert(…) showStoric(…) listRefertForErogants(…) refertToEvent(…) updateRefert(…) 75 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Il cuore del sistema è rappresentato dalla classe WSRepository che, appoggiandosi alle classi Application, DateTime, FileUtil e StringUtil (blocchi verdi), offre una serie di funzioni che permettono la gestione del repository. In figura è evidenziata la struttura della classe con i metodi esposti (quelli nel riquadro di colore fucsia), cioè quei metodi che costituiscono l’interfaccia con cui è possibile comunicare con l’oggetto. Sarà poi questa interfaccia ad essere tradotta da codice Java in un file WSDL, ovvero il documento xml che descrive i metodi forniti da un Web-Service. Questo file viene poi pubblicato e reso disponibile a chiunque voglia fruire di uno dei servizi web forniti, per visualizzarlo basta richiamare l’URL WSRepository?wsdl a partire dal percorso che contiene il Web-Service. Questo file è fondamentale nell’architettura distribuita, perchè rappresenta come è possibile comunicare e interagire con il server e quindi anche come costruire un client che lo possa sfruttare. In ambiente Java è presente un tool, Java2WSDL, che automatizza questo processo e si carica del tedioso lavoro di creazione del file descrittore WSDL a partire da una classe Java. Ad ogni metodo pubblico della classe corrisponderà un metodo del web service, richiamabile attraverso una URL in un formato particolare: WSRepository?method=”nome del metodo”&”nome del parametro”=”valore del parametro”&... Dall’altra parte, è presente un tool che compie il lavoro inverso: WSDL2Java, a partire dal descrittore WSDL crea le classi per una minima implementazione del client. Per maggiori informazioni su questi tool è possibile consultare la documentazione della Sun. Vediamo ora una panoramica dei metodi esposti dalla classe WSRepository. Anche se il cuore del sistema è costituito dalla classe WSRepository, quest’ultima sgrava i suoi compiti alla classe Application che contiene l’implementazione effettiva dei servizi messi a disposizione del Web-Service. Per cui di seguito verrà trattata l’implementazione dei metodi di Application. 76 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED All’interno di essa, una qualsiasi applicazione JDBC deve: 1. Creare una connessione con il DataBase 2. Creare un oggetto Statement per interrogare il database. 3. Interagire con il database. 4. Gestire i risultati ottenuti. Come detto ogni servizio richiede inizialmente di creare una connessione al DataBase, che viene realizzata tramite il metodo setConnection(). setConnection(): L'API JDBC, racchiusa nel package java.sql.*, fornisce un'interfaccia unificata per l'accesso ad un qualunque database, "mascherando" le peculiarità di ogni singolo DBMS introducendo il concetto di driver. Per capire meglio cosa questo significhi basta dare un'occhiata alla documentazione del pacchetto java.sql: ci si accorge immediatamente che la maggior parte delle funzionalità vengono fornite tramite interfacce (cioè tipi puramente astratti), mentre le classi vere e proprie sono davvero poche. Cosa implica tutto ciò? Semplicemente, l'API JDBC si limita in gran parte a dichiarare le funzionalità che un'interfaccia generalizzata per l'accesso ad un database dovrebbe avere, delegando l'implementazione delle interfacce ai driver che devono fornire l'accesso ai singoli DBMS. Quindi, compito di un driver JDBC è fornire un insieme di classi che implementino tutte le interfacce dichiarate nel pacchetto java.sql. I parametri di connessione vengono recuperati da un file di Properties tramite l’istruzione di load(…). Il file DBConfig2 contenente tutti i parametri di connessione ed è situato nella cartella di installazione del TOMCAT, mentre per recuperare informazioni scritte sul file viene usato il comando getProperty(…). Quindi in tal modo è possibile (props.getPropery(“JDBCConnectionURL.1”) recuperare e il driver l’URL di connessione necessario per la connessione(props.getPropery(“JDBCConnectionURL.1”). 77 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED L’istruzione successiva carica in memoria il driver JDBC per l’accesso al DBMS, infatti le specifiche JDBC redatte dalla Sun prevedono che, per poter essere utilizzato, un driver JDBC deve essere caricato in memoria, e una volta che ciò è avvenuto, il driver stesso ha il compito di registrarsi presso il Driver Manager, il quale ha quindi il compito di tenere traccia dei driver JDBC disponibili, in modo da poter costruire correttamente le istanze delle classi che implementano l'interfaccia java.sql.Connection quando queste vengono richieste dalle applicazioni. Successivamente vengono recuperate dal file di Property la Username per accedere al DB (props.getProperty("UserName.1")) e la password (props.getProperty("UserName.1")). Tramite l’istruzione setPropery() assegno alla stringa jdbc.driver il valore di driver_class, ovvero il driver per la connessione al DB. E’ molto importante settare il Driver in quanto converte chiamate JDBC in chiamate di rete dirette utilizzando protocolli di rete specifici del database (socket), inoltre è semplice da utilizzare in quanto non richiede di avere librerie o software speciali. Ottenere una connessione al database tramite JDBC è abbastanza semplice ed indipendente da quale tipo di DBMS si stia utilizzando. E’ necessario solamente indicare all’applicazione, tramite il DriverManager, quale driver utilizzare e farsi rilasciare un oggetto Connection che servirà per dialogare con la base dati. E’ da notare che per identificare il database è necessario specificare l’URL, ossia l’indirizzo verso il quale tentare la connessione. Questa stringa può variare in base al tipo di driver utilizzato, e, alcune volte, può richiedere anche la specificazione di login e password dell’utente, come nel nostro caso. La classe DriverManager non è l'unica che permette la connessione con un DB, ma è possibile utilizzare anche l'interfaccia Driver che permette di accedere a tutte le informazioni che riguardano il db. JDBC permette di sfruttare una delle caratteristiche piu' importanti dei Database ovvero la gestione delle transazioni. Tale gestione si effettua attraverso due semplici metodi della classe Connection: commit e rollback. Il significato dei due metodi e' quello che ci si aspetta: il metodo commit rende definitive tutte le modifiche apportate usando la connessione fino al precedente commit o rollback, viceversa il metodo rollback le annulla fino al precedente commit. 78 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED All'apertura di una connessione la connessione stessa puo' rendere definitiva ogni singola modifica senza bisogno di chiamare esplicitamente il metodo commit (Auto Commit). Per fare in modo che la semantica dei metodi commit e rollback sia quella descritta prima dobbiamo togliere l'Auto Commit nella connessione usando il metodo setAutoCommit(false). E' chiaro che i metodi per la gestione delle transazioni hanno effetto su tutte e sole le operazioni effettuate sul DB tramite la connessione su cui vengono invocati i metodi stessi. public void setConnection() throws IllegalAccessException , InstantiationException , ClassNotFoundException , SQLException , FileNotFoundException , IOException{ try { Properties props= new Properties(); FileInputStream in = new FileInputStream(System.getProperty("catalina.home")+ File.separator+"DBConfig2"); props.load(in); in.close(); String connectionURL=props.getProperty("JDBCConnectionURL.1"); String driver_class= props.getProperty("JDBCDriver.1"); Class.forName (driver_class).newInstance(); String dbUser= props.getProperty("UserName.1"); String dbPassword= props.getProperty("Password.1"); System.setProperty("jdbc.drivers", driver_class); conn = DriverManager.getConnection(connectionURL, dbUser, dbPassword); conn.setAutoCommit(false); System.out.println("Connected.\n"); } catch (IllegalAccessException e) { System.out.println("Illegal Access Exception: (Open Connection)."); e.printStackTrace(); throw e; } catch (InstantiationException e) { System.out.println("Instantiation Exception: (Open Connection)."); e.printStackTrace(); throw e; } catch (ClassNotFoundException e) { System.out.println("Class Not Found Exception: (Open Connection)."); e.printStackTrace(); throw e; } catch (SQLException e) { System.out.println("Caught SQL Exception: (Open Connection)."); e.printStackTrace(); throw e; } catch (FileNotFoundException e) { System.out.println("Caught : FileNotFoundException (Open connection)."); e.printStackTrace(); throw e; } } 79 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Come file di Properties è stato utilizzato un semplice file di testo all’interno del quale sono settati i valori assegnati alle variabili per la connessione, ovvero il driver, l’URL di connessione, la Username e la Password. String driver_class = "oracle.jdbc.driver.OracleDriver"; String connectionURL = "jdbc:oracle:thin:@172.18.11.201:1521:ora920"; String dbUser="STAGE04"; String dbPassword="STAGE04"; authentication(): Ogni servizio per implementare un maggior livello di sicurezza richiede come parametro username e password. Tramite la funzione authentication() il Web-Service va a controllare nel proprio database l’esistenza effettiva dell’utente che ha richiesto di essere loggato. Ciò equivale a realizzare la seguente query: SELECT count(*) from tm_utenti,tm_unitaeroganti WHERE utn_username='"+username+"' AND utn_password='"+password+"' AND utn_codente=uer_codente AND utn_codstruttura=uer_codstruttura AND utn_codspecialita=uer_codspecialita AND utn_codunitaerogante=uer_codunitaerogante Se il risultato è diverso da zero (dovrebbe essere al massimo uguale ad uno), significa che il Web-Service ha riconosciuto l’utente come utente autorizzato e gli permette l’accesso all’interno dell’applicazione. 80 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED userInfo(): Tale metodo restituisce tutte le informazioni relative ad un dato utente. setConnection(); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT utn_id, utn_type, utn_codente, utn_codstruttura, utn_codspecialita FROM tm_utenti WHERE utn_cn = " + StringUtil.quoteString(utn_cn)); if (rs.next()) { info = rs.getInt(1) + ";" + rs.getString(2) + ";" + rs.getString(3) + ";" + rs.getString(4)+";"+rs.getString(5); } rs.close(); stmt.close(); conn.close(); Come visto precedentemente la connessione al database viene effettuata tramite il metodo setConnection(), successivamente viene creato lo Statement e il ResultSet a cui viene assegnato il risultato della query. I comandi di scrittura come INSERT, UPDATE e DELETE restituiscono un valore che indica quante righe sono state affette (inserite, modificate, cancellate) dall'istruzione. Essi non restituiscono altre informazioni. Le interrogazioni (query) restituiscono un result set (classe ResultSet). È possibile spostarsi nel result set riga per riga (tramite il metodo next()). Si può accedere alle colonne di ogni singola riga chiamandole per nome o per numero. Il ResultSet può essere costituito da un numero qualsiasi di righe. Esso comprende dei metadati che indicano il nome, il tipo e le dimensioni delle colonne. Per le stringhe viene utilizzato il metodo quoteString() della classe StringUtil contenente funzioni di utilità per la loro gestione, soprattutto in fase di interfacciamento con i data base (query e insert). 81 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED listEvents(double utn_id, double days): Metodo usato dal refertante, che ritorna l’elenco degli eventi che il dottore è in grado di refertare/visualizzare. Essendo un metodo utilizzato dal refertante inizialmente vi è una select che controlla se l’utente è un erogante. In caso positivo viene fatto un controllo sul tipo di esami che l’erogante è in grado di refertare, tramite la seguente query: SELECT per_tes_codice FROM TM_PERMISSIONI WHERE per_utn_id = "+utn_id+" cioè restituisce il codice che identifica il tipo di esame di possibile refertazione. I valori ottenuti dall’interrogazione devono essere inviati al client per alimentare una griglia, quindi viene creato un file xml contenente il risultato della query. fileName=FileUtil.createXML("SELECT evt_id, evt_dateopen, evt_utn_id, utn_cn, evt_trf_codice, tes_descr, evt_sesso, evt_razza, evt_eta, evt_altezza,evt_um_altezza, evt_peso, evt_um_peso, evt_memo,COUNT(REF_IND) REFERTI FROM TM_EVENTI, TM_TIPOESAMI, TM_UTENTI, TM_REFERTI WHERE evt_utn_id=utn_id AND evt_trf_codice=tes_codice AND evt_trf_codice IN (" +sql_viewexams+ ") AND evt_dateclose IS NULL AND EVT_ID=REF_EVT_ID(+) AND evt_dateopen>=SYSDATE-"+days+" GROUP BY evt_id, evt_dateopen, evt_utn_id, utn_cn, evt_trf_codice, tes_descr, evt_sesso, evt_razza, evt_eta, evt_altezza, evt_um_altezza, evt_peso, evt_um_peso, evt_memo ORDER BY REFERTI","ListEventE",(int)utn_id) Ma come è possibile creare un file XML a partire da una query? Il linguaggio di programmazione java, mette a disposizione tramite la libreria javax.xml delle funzioni che permettono di fare ciò, ovvero di incapsulare i risultati della query all’interno di tag XML. Il codice utilizzato per realizzare tale scopo è il seguente: 82 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance(); DocumentBuilder db=dbf.newDocumentBuilder(); Document doc=db.newDocument(); Element root=doc.createElement("root_element"); //connect to database Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(querySQL); ResultSetMetaData rsmd = rs.getMetaData(); while(rs.next()){ Element row=doc.createElement("row"); for(int j=1;j<=rsmd.getColumnCount();j++){ String colName=rsmd.getColumnName(j); String colValue=rs.getString(j); Element e=doc.createElement(colName); e.appendChild(doc.createTextNode(colValue)); row.appendChild(e); } root.appendChild(row); } doc.appendChild(root); TransformerFactory tmf=TransformerFactory.newInstance(); Transformer tf=tmf.newTransformer(); DOMSource source=new DOMSource(doc); //write to the stream StreamResult result=new StreamResult(fileFullName); tf.transform(source,result); Creato il file Xml contenente il risultato della query, esso viene inviato come allegato tramite il seguente frammento di codice: message=(org.apache.axis.MessageContext.getCurrentContext()).getRes ponseMessage(); message.addAttachmentPart(message.createAttachmentPart(newDataHandl er(new URL("file:"+File.separator+fileNamePath+fileName)))); Essendo un argomento particolarmente delicato quello inerente agli allegati vi torneremo in un secondo momento. Inoltre, poichè molti degli altri servizi implementati, utilizzano la tecnica appena vista (creazione del file XML e invio come allegato), non ci soffermeremo dettagliatamente sulla loro descrizione. 83 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED openEvent(…): Il metodo OpenEvent permette ad un richiedente di inserire un nuovo evento che poi sarà soggetto a refertazione. E’ uno dei pochi casi in cui non c’è la creazione del file xml e il suo funzionamento è semplicissimo: • Ha come parametri le informazioni necessarie al nuovo evento • Prende tali parametri e fa un “INSERT” all’interno del database Ora poiché la tabella oggetto dell’insert ha un campo BLOB (Binary Large OBject) destinato a ricevere la codifica binaria dell’allegato (la documentazione relativa ad un esame, eg. immagine di una radiografia o di una tac ecc…) abbiamo la necessità di una particolare gestione: • Occorre dapprima inserire un “EMPTY_BLOB” nel campo BLOB della tabella (FASE 1) • Selezionare tramite una query l’EMPTY_BLOB appena inserito (FASE 2) • Recuperare il vero BLOB come attachment (FASE 3) • Sovrascrivere l’EMPTY_BLOB con l’effettivo BLOB (FASE 4) Vediamo come tutto questo viene realizzato: FASE 1: setConnection(); stmt = conn.createStatement(); stmt.execute("INSERT INTO tm_eventi (evt_utn_id, evt_trf_codice, evt_dateopen, evt_codice_esterno, evt_sesso, evt_eta, evt_altezza, evt_um_altezza, evt_peso, evt_um_peso, evt_memo, evt_nomeallegato, evt_allegato) VALUES ("+utn_id+","+StringUtil.quoteString(evt_trf_codice)+ ",TO_DATE('"+DateTime.getCurrentDateTime()+"','YYYYMM-DD HH24:MI:SS'),"+ StringUtil.quoteString(evt_codice_esterno) + "," + StringUtil.quoteString(evt_sesso) + "," + evt_eta + "," + evt_altezza + "," + StringUtil.quoteString(evt_um_altezza) + "," + evt_peso + ","+ StringUtil.quoteString(evt_um_peso) + "," + StringUtil.quoteString(evt_memo)+","+ StringUtil.quoteString(evt_nomeallegato.trim())+ ",EMPTY_BLOB())"); stmt.close(); 84 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED FASE 2: stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT MAX(EVT_ID) FROM TM_EVENTI WHERE EVT_UTN_ID="+ utn_id); if (rs.next()) evt_id=Integer.parseInt(rs.getString(1)); stmt.close(); stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT EVT_ALLEGATO FROM TM_EVENTI WHERE EVT_ID="+evt_id+" FOR UPDATE NOWAIT"); FASE 3: if (rs.next()) { oracle.sql.BLOB bcol = ((OracleResultSet)rs).getBLOB(1); OutputStream blobOutputStream = bcol.getBinaryOutputStream(); //Recupera allegato dal messaggio di richiesta del client message=(org.apache.axis.MessageContext.getCurrentContext()).getRequestMess age(); Iterator attachments = message.getAttachments(); //Se non ci sono attachment ritorna -5 if(!attachments.hasNext())return -5; //Prendo solo il primo allegato att = (AttachmentPart) attachments.next(); DataHandler dh = att.getActivationDataHandler(); //Ottengo la codifica in byte dell'allegato BufferedInputStream bis = new BufferedInputStream(dh.getInputStream()); byte[] bs = new byte[bis.available()]; bis.read(bs, 0, bs.length); bis.close(); FASE 4: //Inserisco la codifica in byte dell'allegato nel campo BLOB del DB blobOutputStream.write(bs, 0, bs.length); blobOutputStream.flush(); blobOutputStream.close(); System.out.println("Generato nuovo evento con id "+(int)evt_id+"."); stmt.close(); conn.close(); 85 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED closeEvent(int evt_id): Tale metodo aggiorna lo stato dell’evento a chiuso, ovvero l’utente richiedente ha deciso che non ha più bisogno di ulteriori refertazioni. Per fare ciò va a valorizzare il campo evt_dateclose della tabella eventi con la data corrente: setConnection(); Statement stmt = conn.createStatement(); stmt.execute("UPDATE tm_eventi SET evt_dateclose = TO_DATE('" + DateTime.getCurrentDateTime()+"','YYYY-MM-DD HH24:MI:SS') WHERE EVT_ID= "+evt_id); System.out.println("Evento "+(int)evt_id+" chiuso con successo."); stmt.close(); conn.close(); downloadEvent(double evt_id): Permette ad un client (refertante) di scaricare la documentazione relativa ad un dato evento che egli intende refertare. La procedura consta di 4 passi: • Recupero dal database del nome del file relativo all’evento richiesto dal client • Lettura dal database del BLOB corrispondente all’evento richiesto • Scrittura del BLOB in un file fisico • Invio del file appena creato come attachment setConnection(); //Recupero nome del file Statement stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT TRIM(EVT_NOMEALLEGATO) EVT_NOMEALLEGATO FROM TM_EVENTI WHERE EVT_ID= "+evt_id); if (rs.next()) fileName=rs.getString(1); stmt.close(); String fileFullName=fileNamePath+fileName.trim(); 86 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED //Recupero del BLOB stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT EVT_ALLEGATO FROM TM_EVENTI WHERE EVT_ID= "+evt_id); if (rs.next()) { oracle.sql.BLOB bcol =((OracleResultSet)rs).getBLOB(1); //Scrittura del blob su un file fisico long inizio=1; dati = bcol.getBytes(inizio,(int)bcol.length()); FileOutputStream inn=new FileOutputStream(fileFullName); for(int i=0;i<dati.length;i++) inn.write(dati[i]); inn.close(); //Invio del file come attachment message=(org.apache.axis.MessageContext.getCurrentContext()).getResp onseMessage(); /*LINUX*/ message.addAttachmentPart(message.createAttachmentPart(new DataHandler(new URL("file:"+File.separator+File.separator+fileNamePath+fileName)))); /*WINDOWS*/ //message.addAttachmentPart(message.createAttachmentPart(new DataHandler(new URL("file:"+File.separator+fileNamePath+fileName)))); //Cancellazione del file dalla cartella temp del Tomcat FileUtil.deleteFiles(); System.out.print("Download documentazione evento "+(int)evt_id+" scaricata con successo."); } stmt.close(); conn.close(); referta(…): Analogo ad openEvent(), esso inserisce nella tabella dei referti l’evento appena refertato. Anche in tal caso è presente un attachment, quindi un campo BLOB (documentazione del referto) che deve essere gestito allo stesso modo a quanto fatto precedentemente. 87 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Vediamo com’è stata strutturata la query d’inserimento: setConnection(); stmt = conn.createStatement(); String query="INSERT INTO tm_referti (ref_evt_id, ref_utn_id, ref_datereferto, ref_nomeallegato_referto, ref_allegato_referto, ref_memo, ref_definitivo) VALUES ("+ ref_evt_id + "," + ref_utn_id + ",TO_DATE('" + DateTime.getCurrentDateTime()+"','YYYY-MM-DD HH24:MI:SS'),"+ StringUtil.quoteString(ref_nomeallegato_referto.trim()) +",EMPTY_BLOB()," + StringUtil.quoteString(ref_memo)+","+ StringUtil.quoteString(ref_definitivo)+")"; stmt.execute(query); stmt.close(); listEventReferted(double utn_id): Visualizza gli eventi refertati relativi ad un specificato utente. E’ costituito dalla solita struttura: Creazione xml Invio come attachment Ci soffermiamo alla query con la quale viene creato l’xml: fileName= FileUtil.createXML("SELECT evt_id, evt_trf_codice, tes_descr, evt_dateopen,evt_codice_esterno, COUNT(REF_IND) REFERTI FROM TM_EVENTI, TM_TIPOESAMI, TM_UTENTI, TM_REFERTI WHERE evt_utn_id=utn_id AND evt_trf_codice=tes_codice AND evt_dateclose IS NULL AND EVT_ID=REF_EVT_ID(+) AND utn_id="+utn_id+" GROUP BY evt_id, evt_trf_codice, tes_descr, evt_dateopen,evt_codice_esterno ORDER BY REFERTI DESC","ListEventR",(int)utn_id); 88 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED listEventRefertedByEvtId(double ref_evt_id): Permette di visualizzare tutte le refertazioni relative ad un dato evento (ogni evento può avere più di una refertazione). Anch’esso si basa sul binomio creazione xml e invio come attachment: fileName= FileUtil.createXML("SELECT REF_IND, REF_UTN_ID, UTN_CN,REF_DATEREFERTO, TES_DESCR,REF_NOMEALLEGATO_REFERTO, REF_MEMO,REF_DEFINITIVO FROM TM_EVENTI,TM_REFERTI, TM_UTENTI, TM_TIPOESAMI WHERE EVT_TRF_CODICE=TES_CODICE AND UTN_ID=REF_UTN_ID AND REF_EVT_ID="+ref_evt_id+" AND EVT_ID=REF_EVT_ID","ListRefertByEvtId", (int)ref_evt_id); downloadRefert(double ref_ind): Così come un refertante scarica la documentazione relativa all’evento che egli vuole refertare, allora alla stessa maniera un utente richiedente a refertazione ultimata chiede di scaricare il referto relativo alla sua richiesta. setConnection(); //Recupero nome del file Statement stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT TRIM(REF_NOMEALLEGATO_REFERTO) REF_NOMEALLEGATO_REFERTO FROM TM_REFERTI WHERE REF_IND= "+ref_ind); if (rs.next()) fileName=rs.getString(1); stmt.close(); String fileFullName=fileNamePath+fileName.trim(); stmt = conn.createStatement(); 89 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED //Recupero del BLOB rs = stmt.executeQuery("SELECT REF_ALLEGATO_REFERTO FROM TM_REFERTI WHERE REF_IND= "+ref_ind); if (rs.next()) { oracle.sql.BLOB bcol =((OracleResultSet)rs).getBLOB(1); //Scrittura del blob su un file fisico long inizio=1; dati = bcol.getBytes(inizio,(int)bcol.length()); FileOutputStream inn=new FileOutputStream(fileFullName); for(int i=0;i<dati.length;i++){ inn.write(dati[i]); } inn.close(); //Invio del file come attachment message=(org.apache.axis.MessageContext.getCurrentContext()).getResp onseMessage(); /*LINUX*/ message.addAttachmentPart(message.createAttachmentPart(new DataHandler(new URL("file:"+File.separator+File.separator+fileNamePath+fileName)))); /*WINDOWS*/ //message.addAttachmentPart(message.createAttachmentPart(new DataHandler(new URL("file:"+File.separator+fileNamePath+fileName)))); System.out.print("Download referto "+(int)ref_ind+" effettuato con successo."); //Cancellazione del file dalla cartella temp del Tomcat FileUtil.deleteFiles(); } stmt.close(); conn.close(); showStoric(double utn_id): Permette di visualizzare lo storico degli eventi di un determinato utente, ovvero gli eventi che l’utente stesso ha deciso di chiudere. Anch’esso a partire da una query genera un file xml che poi verrà inviato come attachment. La query è la seguente: SELECT evt_id, evt_trf_codice, tes_descr, evt_dateopen,evt_dateclose, evt_nomeallegato, evt_codice_esterno, evt_memo,COUNT(REF_IND) REFERTI FROM TM_EVENTI, TM_TIPOESAMI, TM_UTENTI, TM_REFERTI WHERE evt_utn_id=utn_id AND evt_trf_codice=tes_codice AND evt_dateclose IS NOT NULL AND EVT_ID=REF_EVT_ID(+) AND utn_id="+utn_id+" GROUP BY evt_id, evt_trf_codice, tes_descr, evt_dateopen,evt_dateclose, evt_nomeallegato, evt_codice_esterno, evt_memo ORDER BY REFERTI Il filtro fondamentale è la presenza di una data di chiusura non nulla. 90 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED listRefertForErogants(double utn_id, double days): E’ un servizio destinato ad un utente refertante e permette di visualizzare i referti da egli effettuati che sono ancora aperti, ovvero che non sono stati dichiarati, sempre dallo stesso refertante, definitivi. Inoltre tali referti sono filtrati secondo una specifica data, cioè il refertante può consultare solamente quei referti che hanno una data di refertazione che rientri in un range stabilito dalla data corrente e dai giorni selezionati da lui stesso nell’interfaccia di visualizzazione. Tramite una query viene creato un file xml che poi viene inviato al client come allegato. Query: SELECT ref_ind, ref_evt_id, evt_utn_id, utn_cn, evt_trf_codice, tes_descr, ref_datereferto, ref_definitivo FROM TM_EVENTI, TM_TIPOESAMI, TM_UTENTI, TM_REFERTI WHERE evt_utn_id=utn_id AND evt_trf_codice=tes_codice AND evt_trf_codice IN (SELECT per_tes_codice FROM TM_PERMISSIONI WHERE per_utn_id = ref_utn_id) AND evt_dateclose IS NULL AND EVT_ID=REF_EVT_ID(+) AND ref_datereferto>=SYSDATE-"+days+" AND ref_utn_id="+utn_id+" ORDER BY REF_DEFINITIVO refertToEvent(double ref_ind): Permette di visualizzare le informazioni di interesse relative alla richiesta di un evento che è stato gia refertato, ad esempio tipo e codice esame, caratteristiche fisiche del richiedente, informazioni sul referto. Tale servizio viene invocato nel momento in cui un utente erogante (refertante) decide di consultare la refertazione di un evento che ha già subito delle refertazioni da parte dell’utente stesso o da altri utenti autorizzati. In tal caso vedrà visualizzate oltre alle informazioni dell’evento anche la diagnosi con tanto di referto allegato. Tutte le informazioni verranno visualizzate lato client in una griglia alimentata tramite un file xml creato attraverso la seguente query: 91 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED SELECT ref_evt_id, evt_trf_codice, tes_descr, ref_definitivo, ref_memo, evt_sesso, evt_eta, evt_peso, evt_um_peso, evt_altezza, evt_um_altezza, evt_memo, ref_nomeallegato_referto FROM TM_EVENTI, TM_TIPOESAMI, TM_UTENTI, TM_REFERTI WHERE evt_utn_id=utn_id AND ref_evt_id=evt_id AND evt_trf_codice=tes_codice AND evt_trf_codice IN (SELECT per_tes_codice FROM TM_PERMISSIONI WHERE per_utn_id = ref_utn_id) AND evt_dateclose IS NULL AND EVT_ID=REF_EVT_ID(+) AND ref_ind="+ref_ind updateRefert(double ref_ind, ….): Consente ad un utente refertante di poter modificare un qualsiasi suo referto dichiarato non definitivo. E’ analogo al servizio “referta”, l’unica differenza sta nella query: si usa un UPDATE anziché INSERT. setConnection(); stmt = conn.createStatement(); String query="UPDATE tm_referti SET REF_NOMEALLEGATO_REFERTO="+ StringUtil.quoteString(ref_nomeallegato_referto.trim()) + "," + " REF_MEMO="+StringUtil.quoteString(ref_memo)+ "," + " REF_DEFINITIVO="+StringUtil.quoteString(ref_definitivo)+ "," +" REF_DATEREFERTO=TO_DATE('"+DateTime.getCurrentDateTime()+ "','YYYY-MM-DD HH24:MI:SS')"+" WHERE REF_IND="+ref_ind; stmt.execute(query); stmt.close(); Per il campo BLOB viene utilizzata la stessa procedura ampliamente descritta in alcuni dei servizi precedenti. updateRefertWithoutBLOB(double ref_ind, ….): E’ il servizio precedente senza però l’update del campo BLOB. 92 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED login(String user, String pswd): Il servizio di login è molto simile al servizio “authentication”, ma leggermente più completo. Infatti oltre ad andare a verificare l’esistenza dell’utente che ha richiesto l’accesso all’applicazione sul database, esso, in caso affermativo, invia al client un file xml contenete le informazioni principali dell’utente appena loggato, cosicché queste possano essere visualizzate nell’interfaccia migliorando l’estetica e la leggibilità. Tramite una query si reperiscono le informazioni dell’utente che vengono poi incapsulate in un file xml e inviate come allegato al client. Query: String query="SELECT utn_id, utn_cn, utn_type, utn_codente, utn_codstruttura, utn_codspecialita, utn_codunitaerogante, uer_descr FROM tm_utenti,tm_unitaeroganti WHERE utn_username='"+user+"' AND utn_password='"+pswd+"' AND utn_codente=uer_codente AND utn_codstruttura=uer_codstruttura AND utn_codspecialita=uer_codspecialita AND utn_codunitaerogante=uer_codunitaerogante"; 93 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED 5.3 Fase di deploy Lo schema proposto dalla Sun Microsystem in quanto a Web Applications propone un modello descrittivo dell'alberatura del progetto in modo da separare e descrivere meglio tutta l'applicazione. Questo approccio ha, come sappiamo, gli indubbi vantaggi della standardizzazione. Da una parte consente a chi produce i tool di sviluppo e gli application server di rendersi compatibili (e magari certificati da Sun) con le nuove specifiche, dall'altra permette a chi sviluppa applicazioni Web di sapere che la struttura dell'applicazione deve essere fatta in un certo modo e che un qualunque application server, se certificato, tratterà l'applicazione allo stesso modo, garantendo quindi la portabilità assoluta. Il nodo centrale della standardizzazione è dato da una definizione precisa dell'alberatura dell'applicazione. Come sappiamo la root della Web Application dovrà contenere le pagine HTML o JSP. In alcuni casi le pagine JSP possono essere anche nella cartella JSP, in "css" ci sono i fogli di stile, in "js" i file contenenti codice Javascript e dentro "WEB-INF" c'è una determinata alberatura. In particolare a partire dalla cartella "classes" vengono espansi i package Java dell'applicazione, in "conf" ci sono i file deputati alla configurazione applicativa, in "lib" tutte le librerie esterne sotto forma di JAR o ZIP, in "tld" eventuali tag libraries, in "log" i log dell'applicazione. Supponiamo di aver creato la nostra applicazione utilizzando questo schema, ad un certo punto sarà necessario effettuare il deploy su una macchina differente da quella di sviluppo. La macchine di sviluppo, soprattutto se si utilizzano ambienti di sviluppo molto sofisticati, sono configurate diversamente da quelle di test, pertanto il passaggio da un ambiente all'altro potrebbe non essere indolore. 94 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Deploy - modo tradizionale Per eseguire il deploy di questa Web Application in modo tradizionale, se si utilizza Tomcat come application server, è necessario copiare l'alberatura così com'è sul file system della macchina server ed editare il file TOMCAT_HOME/conf/server.xml aggiungendovi la sezione relativa al nuovo context da creare per poter utilizzare la nuova Web Application attraverso HTTP. La sezione che ci serve è di questo genere: <ContextManager> <Context path="/nomeApplicazione" docBase="c:\nomeApplicazione" crossContext="true" debug="0" reloadable="true" trusted="false" > </Context> </ContextManager> Sarà nostra cura inoltre modificare il CLASSPATH di sistema in modo da includere tutte le librerie esterne che debbano essere utilizzate dalle componenti della nostra applicazione. Questo metodo funziona indipendentemente da come sia organizzata la Web Applicaton. Al termine potremo raggiungere la nostra applicazione attraverso l'url: http://localhost:8080/nomeApplicazione/ 95 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Cosa accade però in fase di manutenzione? In altre parole, cosa succede quando dobbiamo riportare in ambiente di test delle modifiche che coinvolgono alcune parti della Web Application? Ci sono solitamente due alternative: • si sovrascrive l'intera alberatura con la versione aggiornata • si sovrascrivono selettivamente soltanto i file modificati In ogni caso gli interventi da effettuare manualmente sono molti e la procedura non troppo semplice, soprattutto se siamo di fronte ad applicazioni con un certo grado di complessità. Deploy - il file WAR La specifica proposta da Sun non si limita a descrivere l'alberatura per la costruzione dell'applicazione, ma ci consente anche di avere un buon sistema per effettuare il deploy dell'applicazione utilizzando un singolo file, il file WAR. Un file WAR, come sappiamo, viene generato attraverso il tool jar.exe contenuto nel JDK ed è pertanto un semplice file JAR rinominato. Il fatto che sia un WAR e non un JAR, indipendentemente dal contenuto, gli permette di essere automaticamente riconosciuto come una vera e propria Web Application completa e dotata di vita propria, in questo modo l'application server sarà in grado di autoconfigurarsi sapendo che il WAR contiene esattamente quel tipo di struttura. Per effettuare il deploy su Tomcat di un file WAR è sufficiente crearlo, dopo essersi posizionati all'interno della cartella contenente l’applicazione, attraverso il comando: jar cvf nomeApplicazione.war . Dopo aver ottenuto il file nomeApplicazione.war l'operazione di deploy si limita allo spostamento del file WAR all'interno della cartella webapps di Tomcat. 96 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Subito dopo il restart dell'Application Server potremo vedere la nostra applicazione utilizzando il solito url: http://localhost:8080/nomeApplicazione/ Quando l'Application Server parte, si scompatta automaticamente il file WAR e si crea il context per poter raggiungere l'applicazione via http. Utilizzando questo metodo di deploy la manutenzione si riduce ai tre passi seguenti: • creazione del nuovo file WAR • copia del nuovo WAR sulla macchina di test • eliminazione della vecchia alberatura estratta dal WAR precedente Eclipse mette a disposizione un comando per la crazione del file WAR senza dover andare a ricorrere al prompt dei comandi: Figura 5.12. Creazione del WAR file. Cliccare con il tasto destro del mouse sull’icona del progetto e selezionare la voce Export->WAR file. Successivamente verrà richiesta la path di destinazione del file e il nostro WAR è pronto per il deploy. Ora occorre spostare il file WAR appena creato all'interno della cartella webapps di Tomcat. A tal proposito possiamo utilizzare due alternative: • Spostare fisicamente il file nella macchina di sviluppo • Utilizzare il manager del tomcat 97 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Indirizzo del server Path del WAR file Figura 5.13 – Deploy con il manager del Tomcat. Conclusioni I vantaggi della seconda soluzione sono evidenti, è possibile effettuare un deploy su qualsiasi Application server compatibile con le specifiche di Sun semplicemente copiando il file nella posizione giusta ed effettuando il restart. Utilizzando il metodo tradizionale, invece, dovremmo verificare caso per caso qual è la procedura di creazione del context e specificando manualmente il CLASSPATH. La scelta del WAR è indubbiamente la più interessante. Il vero problema è la migrazione di applicazioni scritte utilizzando strutture differenti e molto spesso questa non è un'operazione per niente banale. 98 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED 5.4 Una possibile e particolare implementazione del client Il progetto JTelemed descrive le architetture software e hardware per la realizzazione di un modello client-server per la telerefertazione on-line. Anche se questo elaborato presenta solamente gli aspetti legati allo sviluppo lato server è bene chiarire che esso è stato creato in un aspetto molto più ampio e integrato da un applicativo client. Per capire meglio come client e server possano effettivamente comunicare tra loro è bene dunque fornire qualche breve cenno sulla realizzazione del client. Il client è stato sviluppato grazie ad un tool di sviluppo proprietario della Zucchetti che comprende PortalStudio e SitePainter. Essi sono strumenti potentissimi che facilitano il lavoro di creazione delle classi Java indispensabili nella comunicazione client-server. Uno dei loro aspetti più importanti, che è stato ampiemente utilizzato, è la creazione di griglie di dati alimentate da una query SQL o da un file XML. Infatti nel capitolo 5.2 abbiamo visto che il server forniva quasi sempre come risultato di una generica richiesta da parte di un client un file XML che poi inviava come allegato (attachment) al messaggio SOAP di risposta. Ecco questo file XML non faceva altro che andare ad alimentare la griglia realizzata dai tool del client. Senza perdere troppo tempo andiamo ad analizzare qualche piccolo aspetto del client. La home page dell’applicativo corrisponde alla PAGELET (di SitePainter PortalStudio) pg_inizio_jtelemed.jsp. Tale pagelet prevede 3 frame distinti: - nel frame in alto è caricata la portlet jtelemed_alto_portlet.jsp; - nel frame laterale sinistro è caricata la portlet jtelemed_left_login_portlet.jsp; - nel frame centrale è caricata la portlet di presentazione jtelemed3_portlet.jsp. 99 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Figura 5.14 – Home page di un possibile client. Portlet: jtelemed_alto_portlet Non è altro che una semplice portlet con un’immagine: il banner dell’applicativo. Portlet: jtelemed_left_login_portlet La portlet jtelemed_left_login_portlet.jsp permette all’utente di effettuare il login attraverso gli identificativi username e password. sp_global_var sp_login xmlLogin 100 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Action code function bt_entra_Click() { this.username.Value(this.txt_user.Value()) this.password.Value(this.txt_psw.Value()) var a = this.sp_login.Link() if(a=="true"){ this.xmlLogin.Query() this.sp_global_var.Link() window.open('jtelemed_left_portlet.jsp','frame_left') } else alert(a); } Al click del mouse sul bottone “Entra” vengono presi i valori delle textbox txt_user e txt_psw e passati alle rispettive variabili username e password. A questo punto viene attivato l’SPLinker sp_login che richiama la servlet (Function) ../servlet/fn_login passandogli come parametri le variabili username e password. String home_catalina=System.getProperty("catalina.home"); try{ WSRepositoryServiceLocator wsrl = new WSRepositoryServiceLocator(); WSRepository wsr= wsrl.getWSRepository(); nome_file = wsr.login(username,password); //Recupera l’allegato dal messaggio di risposta del server. Object[] attachments=((WSRepositorySoapBindingStub)wsr).getAttachments(); AttachmentPart att = (AttachmentPart) attachments[0]; DataHandler dh = att.getActivationDataHandler(); FileOutputStream fos = new FileOutputStream(home_catalina+File.separator+"webapps" +File.separator+"jtelemed"+File.separator+"temp"+File.s eparator+nome_file); BufferedInputStream bis=new BufferedInputStream( dh.getInputStream()); byte[] bs = new byte[bis.available()]; bis.read( bs, 0, bs.length ); fos.write( bs ); bis.close(); fos.close(); } catch(Exception e) { File f = new File(home_catalina+File.separator+"webapps"+File.separator+"jtelemed "+File.separator+"temp"+File.separator+nome_file); f.delete(); System.out.println(e); nome_file="Errore nel recupero allegato"; } 101 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED La parte evidenziata in rosso è quella che ci interessa maggiormente in quanto rappresenta la chiamata esplicita a un servizio messo a disposizione dal server: in particolare tale funzione java del client invoca il servizio login del server che, come abbiamo visto nel capitolo 5.2, esegue una query sul database in corrispondenza dei valori passati dal client (username e password relativi all’utente che ha richiesto di loggarsi), crea un file XML con le informazioni (se l’utente è registrato) dell’utente, ritorna come risposta un messaggio SOAP contenente il nome del file appena creato e invia come allegato al messaggio tale file. Tale funzione ha dunque il compito di controllare se l’utente è accreditato ad accedere all’applicativo. Se il ritorno di tale funzione è un valore “true”, viene attivato l’XMLObject xmlLogin che va a leggere un file .xml creato attraverso la precedente funzione e che si trova nella cartella (Source) ../temp/XmlLogin.xml. La struttura del file .xml prevede una intestazione (prima di accedere alla informazioni vere e proprie) del tipo /root_element/row da dichiarare nel campo Root delle proprietà dell’XMLObject. Se la lettura al file .xml è andata a buon fine, vengono automaticamente valorizzate le variabili utn_id, utn_cn, utn_type, utn_codente, utn_codstruttura, utn_codspecialita, utn_codunitaerogante, utn_descr ovvero tutte le informazioni dell’utente appena loggato. Tali variabili infatti sono dichiarate indicando tra le rispettive proprietà il DataObject associato (Dataobj: xmlLogin) ed il campo da utilizzare per il valore dell'elemento (ad esempio per la variabile utn_id si associa Field: UTN_ID). A ../servlet/fn_set_global questo (che punto non viene richiamata affrontiamo) la attraverso funzione il link (Function) all’SPLinker sp_global_var. Tale funzione prende come parametri tutte le informazioni dell’utente ricavate precedentemente dall’XMLObject e li imposta come variabili globali. Attraverso il comando javascript window.open(…) viene caricata la portlet jtelemed_left_portlet.jsp nel frame laterale sinistro frame_left. Se l’utente fosse risultato non accreditato ad accedere all’applicativo viene fornito in output un messaggio di notifica dell’errore. In questo caso non è permesso l’accesso all’applicativo. 102 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Portlet: jtelemed_left_portlet La portlet jtelemed_left_portlet.jsp fornisce all’utente appena loggato un menù di accesso ai servizi. In particolare: a) se l’utente è un RICHIEDENTE sp_logout vengono attivati i bottoni NUOVO EVENTO, EVENTI REFERTATI ed lb_utente lb_tipo image15 EVENTI CHIUSI b) se l’utente è un EROGANTE vengono attivati i bottoni EVENTI APERTI e REFERTI APERTI Nella portlet vengono richiamate le variabili globali g_utn_cn e g_utn_type (impostando tra le proprietà il campo Init par a “global string) che recuperano rispettivamente il CommonName (nome) e il tipo (richiedente/erogante) di utente. In base al valore (R: richiedente , E:erogante) della variabile g_utn_type vengono mostrati (Show()) o nascosti (Hide()) i vari bottoni . Le label lb_utente e lb_tipo vengono valorizzate con il CommonName dell’utente e con l’indicazione del tipo utente. Action code 1 // Codice sicurezza portlet this.lb_utente.Value(this.g_utn_cn.Value()) if(this.g_utn_type.Value()=="R") this.lb_tipo.Value("RICHIEDENTE") else this.lb_tipo.Value("EROGANTE") if(this.g_utn_type.Value()=="R"){ this.image5.Show() // Nuovo evento this.image6.Show() // Eventi refertati this.image7.Show() // Eventi chiusi this.image4.Hide() this.image8.Hide() } else{ this.image4.Show() // Eventi aperti this.image8.Show() // Referti aperti this.image5.Hide() this.image6.Hide() this.image7.Hide() } 103 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Al click dei diversi bottoni vengono caricate diverse portlet attraverso il comando javascript window.open(‘nome_portlet’,’frame_destinazione’). Nel nostro caso le portlet vengono caricate nel frame_centro (ovvero il frame centrale dell’applicativo). In ogni caso è previsto un bottone per effettuare il logout dall’applicativo. Al click di questo bottone (image15) viene richiamata una funzione di SitePainter (Servlet: ../servlet/fn_logout) che resetta le variabili globali e reindirizza l’utente alla home page. Tale funzione è richiamata attraverso l’SPLinker sp_logout che non necessita di alcun parametro. //----Funzioni----- Action code 2 function image6_Click(){ window.open('eventi_refertati_frame_portlet.jsp','frame_centro'); } function image4_Click(){ window.open('eventi_aperti_frame_portlet.jsp','frame_centro'); } function image5_Click(){ window.open('scelta_lingua_portlet.jsp','frame_centro'); } function image7_Click(){ window.open('eventi_chiusi_frame_portlet.jsp','frame_centro'); } function image8_Click(){ window.open('referti_aperti_frame_portlet.jsp','frame_centro'); } function image15_Click(){ this.sp_logout.Link() } Delle numerose portlet che costituiscono il client prenderemo adesso in esame una portlet che realizza un aspetto molto importante accennato in precedenza: alimentare una griglia attraverso un file XML proveniente dal server. 104 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Portlet: eventi_aperti_frame_portlet.jsp (Erogante – Eventi aperti) frame_listevent Attraverso questa portlet un utente EROGANTE potrà avere la lista degli eventi aperti che egli potrà refertare. In particolare, la lista comprenderà solamente gli eventi di sua “competenza”, ovvero gli eventi legati ad una disciplina sulla quale l’erogante ha la permissione. L’utente potrà visionare gli eventi aperti negli ultimi 3 giorni, ultimi 7 giorni, ultimi 15 giorni, ultimi 30 giorni, ultimi 60 giorni. Cliccando sul bottone “Visualizza” viene caricata la portlet listevent_portlet.jsp nel frame frame_listevent. Se l’utente non seleziona un periodo di riferimento per la query, viene settato il valore massimo di 60 giorni. //-----Funzioni---- Action code function bt_download_Click() { if(this.combo_periodo.Text()=='-') this.combo_periodo.Value('60') window.open('../jsp/listevent_portlet.jsp?utn_id='+this.utn_id.Valu e()+'&periodo='+this.combo_periodo.Value(),'frame_listevent'); } 105 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Portlet: listevent_portlet.jsp splinker27 xmlobj7 Quella che si vede in figura è una griglia che riepiloga gli eventi aperti che l’utente può refertare perché di sua competenza. Per ottenere ciò si richiama la funzione del SitePainter ../servlet/fn_listevent (simile per principio di funzionamento alla funzione fn_login) attraverso l’splinker27. A tale funzione è necessario passare l’ID dell’utente refertante (per controllare le discipline di sua competenza) e il periodo richiesto (utn_id,periodo). Questa funzione recupera un file XML creato lato server contenete tutte le informazioni richieste. Questo file XML (../temp/ListaEvent.xml) è letto dall’XMLDataobj xmlobj7 che poi alimenterà la griglia. Action code 1 parent.ZtVWeb.getPortlet('evnti_aperti_frame').nome_file.Value(''); var a=this.splinker27.Link(); parent.ZtVWeb.getPortlet('evnti_aperti_frame').nome_file.Value(a); if(parent.ZtVWeb.getPortlet('evnti_aperti_frame').nome_file.Value() =="-2") { this.Box10.Show() alert("Utente non erogante:accesso negato") } else{ this.Box10.Hide(); this.xmlobj7.Query(); } this.colora(); La griglia permetterà di visualizzare le seguenti informazioni (Columntitles): Evento, Data Apertura, Id Utente, Nome, Codice esame, Descrizione, Referti . 106 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED In particolare, cliccando sul campo Evento si richiama una funzione dell’Action Code(Columnlinks:javascript:ZtVWeb.getPortlet(\'listevent\').download(\'%EVT_ID%\' |\'%EVT_ETA%\'|\'%EVT_SESSO%\'|\'%EVT_ALTEZZA%\'|\'%EVT_UM_ALTEZZA%\'| \'%EVT_UM_PESO%\'|\'%EVT_PESO%\'|\'%EVT_MEMO%\'|\'%TES_DESCR%\'|\'%E VT_RAZZA%\'|'\%REFERTI%\'),,,,,,,). Action code 2 function download(evt_id,eta,sesso,altezza, um_altezza,um_peso, peso, memo, descr,razza,referti) { window.open('../jsp/downloadevent_portlet.jsp?evt_id='+evt_id+'&ra zza='+razza+'&sesso='+sesso+'&eta='+eta+'&peso='+peso+'&altezza='+ altezza+'&memo='+memo+'&esame='+descr+'&um_peso='+um_peso+'&um_alt ezza='+um_altezza+'&referti='+referti+'&utn_ref='+this.utn_id.Valu e(),'frame_listevent','toolbar=no,location=no,scrollbars=no,width= 785,height=560'); } Questa funzione aprirà una portlet che permetterà all’utente di: - visionare maggiori informazioni sull’evento selezionato, - visionare referti di altri eroganti sul medesimo evento - effettuare successivamente una refertazione Figura 5.15 – Griglia del client 107 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED 5.5 Axis Attachments a) Aggiungere un allegato al messaggio SOAP di risposta al client (upload) Codice import import import import import java.io.*; java.net.URL; javax.activation.DataHandler; javax.xml.soap.SOAPMessage; org.apache.axis.attachments.AttachmentPart; // ……Servizio del Web Services…… SOAPMessage message=null; message=(org.apache.axis.MessageContext.getCurrentContext()).getRe sponseMessage(); URL url= new URL("file:"+File.separator+fileNamePath+fileName) message.addAttachmentPart(message.createAttachmentPart(new DataHandler(url)); Poiché si vuole allegare un file al messaggio di risposta del server verso il client, si deve recuperare il Context (contesto) corrente e quindi il relativo messaggio di risposta (getResponseMessage()). Per realizzare ciò si utilizza la classe di Axis org.apache.axis.MessageContext e, in ordine, i metodi getCurrentContext() e getResponseMessage(). La classe SOAPMessage implementa il metodo addAttachmentPart che permette, individuato l’URL del file e creata la classe DataHandler , di creare una sezione del messaggio SOAP in cui posizionare effettivamente l’allegato. 108 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED b) Recuperare un allegato dal messaggio SOAP di richiesta dal client (download) Codice import import import import import java.io.*; java.net.URL; javax.activation.DataHandler; javax.xml.soap.SOAPMessage; org.apache.axis.attachments.AttachmentPart; //……Servizio del Web Services…… message=(org.apache.axis.MessageContext.getCurrentContext()).getRe questMessage(); Iterator attachments = message.getAttachments(); if(!attachments.hasNext())return -5; //Se non ci sono attachment ritorna -5 att = (AttachmentPart) attachments.next(); //Prendo solo il primo allegato DataHandler dh = att.getDataHandler(); BufferedInputStream bis = new BufferedInputStream(dh.getInputStream()); byte[] bs = new byte[bis.available()]; bis.read(bs, 0, bs.length); bis.close(); Poiché si vuole recuperare un allegato dal messaggio di richiesta del client verso il server, si deve recuperare il Context (contesto) corrente e quindi il relativo messaggi di richiesta (getRequestMessage()). La classe SOAPMessage mette a disposizione il metodo getAttachments() che restituisce un iterator degli allegati. Si recupera, quindi, il primo allegato (primo elemento dell’iterator) ed il relativo DataHandler attraverso il metodo getDataHandler(). A questo punto si attivano i canali di stream per la successiva scrittura del file sul file system. 109 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED TCP/IP Monitor Abbiamo più volte parlato del TCP/IP Monitor come uno strumento per il controllo dello scambio di messaggi tra client e server. Vediamo come appare la sua interfaccia: Ora di invio della richiesta, tempo di risposta, protocollo utilizzato Figura 5.16 – Il TCP/IP Monitor di Eclipse Richiesta del client Struttura del messaggio SOAP contenente la richiesta da parte del client di un determinato servizio. Risposta del server Struttura del messaggio SOAP contenente la risposta da parte del server al servizio richiesto dal client. La presenza di un attachement si nota dalla parola chiave _Part_ seguita da un numero di serie. In questo caso il server ha risposto al client inviando un determinato file (nella maggioranza dei casi xml) come allegato. 110 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED 5.6 Comunicazione Client-Server Finora ci siamo occupati della realizzazione software di un server e di un client che permettono lo scambio di esami e referti. Quello che però è stato descritto è ciò che sta alla base del progetto, ciò che sta sotto al progetto e che nessun utente finale è in grado di vedere. Allora in questo paragrafo verrà illustrato come questo applicativo appare agli occhi di un utente, ovvero le interfacce grafiche con le quali un qualsiasi utente autorizzato può ad esempio creare nuovi eventi (nel caso di un utente richiedente) oppure refertare un evento (utente erogante). Figura 5.17 – Home page dell’applicativo JTelemed Innanzitutto nella pagina iniziale è presente un area di accesso riservato in cui vi è l’identificazione dell’utente richiedente o dell’utente che emette il referto. In base all’utente che si autentica si avrà un’interfaccia diversa. 111 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Nella maschera relativa all’ utente RICHIEDENTE è presente una sorta di menù contenente la gestione delle varie richieste, ossia le informazioni relative alla nuova richiesta, lo stato delle richieste non chiuse ovvero il messaggio di consulta delle richieste non chiuse e uno storico delle richieste chiuse entro due mesi dalla data in cui la richiesta viene chiusa. Operazioni possibili di un utente richiedente Informazioni utente: nome e tipo Figura 5.18 – Home page di un utente richiedente Per inserire un nuovo evento il richiedente deve compilare un modulo in cui inizialmente seleziona la lingua (Italiano/Inglese). Successivamente inserisce tutte le informazioni personali quali sesso, età, altezza e peso. Altre informazioni necessarie per identificare la richiesta sono: Riferimento della richiesta, il tipo di riferimento, un campo note (per eventuali chiarimenti) e un campo Allegati in cui è possibile inserire degli allegati, ovvero documenti digitali relativi agli esami effettuati. 112 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Figura 5.19 – Maschera di inserimento di un nuovo evento Cliccando sulla voce “Eventi refertati” vengono visualizzati tutti gli eventi per cui l’utente richiedente apena loggato ha richiesto una refertazione. Numero di referti per un dato evento Link ai dettagli di un dato evento Possibilità di chiudere un evento Figura 5.20 – Maschera di visualizzazione degli eventi aperti e refertati 113 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Selezionando invece “Eventi chiusi” appare una maschera simile alla precedente nella quale sono elencati tutti gli eventi generati da un dato utente che per qualche motivo sono stati chiusi, ovvero l’utente ha deciso che non è più interessato ad alcuna refertazione o ad alcuna ulteriore refertazione. Figura 5.21 – Maschera di visualizzazione degli eventi chiusi Un evento chiuso non è più visibile da un refertante. Nella maschera relativa all’utente che effettua il referto è presente un menù contenente un link ad una lista degli eventi aperti ed uno ai referti non definitivi. Quando parliamo di lista di referti o lista di eventi aperti bisogna specificare che essi sono tutti quelli del tipo per cui un utente erogante è specializzato, ovvero, per esempio, se l’utente è un radiologo egli potrà refertare solo esami di radiologia (e non ad esempio quelli di virologia).Tali liste potranno essere consultate dai refertanti i quali in seguito potranno dare un loro parere. Operazioni possibili di un utente erogante Informazioni utente: nome e tipo Figura 5.22 – Maschera di visualizzazione degli eventi aperti per un refertante 114 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Filtro per data Figura 5.23 – Maschera di visualizzazione degli eventi aperti per un refertante Per inserire un referto è necessario cliccare sull’evento (nell’esempio il 469); si aprirà una finestra con tutti i dettagli e con la possibilità di scaricare la documentazione relativa all’evento. Figura 5.24 – Dettagli di un evento 115 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Successivamente occorre compilare un modulo che ha la seguente forma: Figura 5.25 – Modulo per la refertazione Compilato il modulo e inserito il referto come allegato per inoltrarlo al servar basta premere il pulsante “Invia referto”. Infine, selezionando dal menù la voce “Referti aperti”, l’utente erogante può consultare le refertazioni che lui stesso ha emesso o che sono in fase di emissione (refertazione non definitiva). Figura 5.26 – Elenco dei referti Sempre dal menù sulla sinistra è possibile disconnettersi e tornare alla pagina iniziale: 116 CAP. 5 – IMPLEMENTAZIONE DEL PROGETTO JTELEMED Figura 5.27 – Menù di un utente erogante 117 CAP. 6 – TECNOLOGIE SOFTWARE Panoramica delle tecnologie software impiegate nella realizzazione del progetto. Maggiori dettagli su aspetti già introdotti nei capitoli precedenti INDICE ARGOMENTI: 6.1 Java Platform 6.1.1 Le Servlet 6.2 Service-Oriented-Architecture 6.2.1 Web-Services 6.2.2 Protocollo SOAP 6.3 Application Server 6.3.1 Apache Tomcat 6.4 Strumenti di sviluppo 6.4.1 Apache Axis 6.5 Database Relazionale 6.5.1 Oracle 6.5.2 FreeTOAD 118 CAP. 6 – TECNOLOGIE SOFTWARE 6.1 Java Platform Fig. 6.1 – Architetture della piattaforma Java Java appena è uscito è stato accolto con molto entusiasmo dalla comunità mondiale dei progettisti di software e dei provider di servizi Internet, questo perché Java permetteva agli utenti di Internet di utilizzare applicazioni sicure e indipendenti dalla piattaforma, che si possono trovare in qualsiasi punto della rete. Java è quindi nato come linguaggio per la rete, per affiancare l'Hyper Text Markup Language (HTML), il quale non è un linguaggio di programmazione vero e proprio, e per dargli quella sicurezza che l'HTML non ha. Da quando è nato Java sulla rete si è iniziato a poter parlare di numeri di carte di credito e di informazioni sicure, notizia che ha molto affascinato le grosse società mondiali, le quali hanno trasformato la vecchia Internet, rete ad appannaggio delle sole università e centri di ricerca, nell'attuale mezzo di comunicazione aperto a tutti. Il linguaggio di programmazione Java è stato creato verso la metà degli anni novanta, è il più recente tra i suoi cugini, e per questo è ancora in fase evolutiva, tanto che ogni anno circa ne viene rilasciata una nuova relase. 119 CAP. 6 – TECNOLOGIE SOFTWARE Da linguaggio nato solo per la rete è divenuto un vero e proprio linguaggio di programmazione, paragonabile, dal punto di vista delle funzionalità, al più blasonato C++. Java e la maggior parte degli altri linguaggi possono essere paragonati solo dal punto di vista delle funzionalità, perché sono fondamentalmente molto diversi, infatti Java compila i sorgenti dei suoi programmi in un codice detto Bytecode, diverso dal linguaggio della macchina su cui è compilato, mentre linguaggi come il C++ compilano i sorgenti dei programmi in un codice che è il codice della macchina ( per macchina intendo computer + sistema operativo ) su cui è eseguito. Quindi per eseguire un programma Java occorre avere uno strumento che è chiamato Java Virtual Machine, la quale interpreta il bytecode generato dal compilatore Java e lo esegue sulla macchina su cui è installato. Grazie alla Java Virtual Machine Java è indipendente dalla piattaforma, infatti il programma compilato Java è legato alla JVM e non al sistema operativo, sarà quindi possibile eseguire lo stesso programma Java, compilato una sola volta su una qualche macchina con un compilatore Java versione X, su una piattaforma Windows e su una piattaforma Linux, per fare questo però c'è bisogno che sia Windows che Linux abbiano installato una Java Virtual Machine che supporti la versione X di Java. Le due JVM installate sulle due piattaforme diverse sono lo stesso programma compilato una volta per Windows ed una volta per Linux, come avveniva con i programmi scritti in linguaggi come il C/C++. Una Java Virtual Machine è implementata anche nei vari Browser (Come Netscape e Explorer) per poter eseguire i programmi Java incontrati nella rete, i cosidetti Applet. Questo però, unito al fatto che Java ancora si evolve, causa degli ovvi problemi di incompatibilità: capita sempre che il più moderno Browser supporti una versione precedente di Java rispetto all'ultima versione rilasciata dalla Sun Microsystem, inoltre bisogna tener presente che non tutti gli utenti di Internet navigano usando l'ultima versione di Netscape o di Explorer. Quindi volendo creare un applet ed inserirlo in un nostro documento HTML, dobbiamo tenere presente questi problemi, e cercare di scrivere un programma che sia compatibile con la maggior parte delle JVM inplementate nei vari browser. 120 CAP. 6 – TECNOLOGIE SOFTWARE Un altro problema da affrontare è quello della scelta del compilatore Java da utilizzare, infatti esistono vari ambienti integrati per editare, compilare, debuggare ed eseguire programmi Java, come quelli della Borland, della Microsoft, della Symantec. Tutti questi ambienti offrono dei tool di sviluppo eccellenti, come editori grafici di finestre, debugger molto interessanti, però hanno due problemi, il primo è che si pagano, anche molto, il secondo è sempre lo stesso della compatibilità, infatti essi spesso si trovano indietro alla relase della sun, ed inoltre aggiungono delle classi che poi le JVM implementate nei browser non hanno. Il consiglio è quello di usare le JDK (Java Development Kit) della Sun, le quali comprendono sia il compilatore che la Java Virtual Machine per eseguire i programmi da noi compilati, inoltre sono freeware (non costano niente) e sono scaricabili dalla rete ed i browser si adeguano pian piano a questa versione di Java. Se volete scrivere applet per i vecchi browser dovete scaricarvi la versione 1.1 di Java. Comunque ad oggi le ultime versioni dei programmi di navigazione più diffusi supportano la più recente release di Java, cioè la 1.5, quella che è stata utilizzata nello sviluppo del progetto. Un ultimo problema che ha Java è la lentezza, infatti, come già detto, esso è interpretato, quindi le istruzioni Java prima di essere eseguite dalla macchina vengono interpretate dalla JVM, ovvero per eseguire ogni istruzione il computer eseguirà un numero di istruzioni macchina che è più del doppio delle istruzioni che eseguirebbe se la stessa istruzione fosse stata scritta in C, quindi avrete bisogno di computer veloci per eseguire bene programmi Java, e di questo vi sarete sicuramente accorti anche navigando sulla rete. Per finire ritorniamo al Java Development Kit della Sun Microsystem, con questo è possibile produrre tutto il software che si vuole senza dover pagare diritti di uso del prodotto come avviene con il Borland Jbuilder, il Symantec Cafe, e il Microsoft Visual Java, vi consigliamo di leggere la licenza d'uso che troverete quando andrete a scaricare il JDK prima di cominciare a produrre software. La principale differenza tra Java e gli altri linguaggi di programmazione ad oggetti è che mentre con questi ultimi è possibile anche programmare ad oggetti con Java si deve assolutamente programmare ad oggetti. Quindi punto fondamentale è spiegare cosa vuol dire programmare ad oggetti. 121 CAP. 6 – TECNOLOGIE SOFTWARE Sostanzialmente la programmazione avviene allo stesso modo dei linguaggi "normali", solo che sia i dati che le funzioni che li manipolano sono racchiusi in delle strutture dette classi. Le classi sono dei prototipi di oggetti, ovvero sono delle strutture astratte che possono essere istanziate e quindi creare un oggetto (ma anche più di uno). La classe definisce tutte le proprietà degli oggetti appartenenti a quella classe, detti attributi, e le funzioni che verranno usate per agire su di essi, detti metodi. Ad esempio è possibile definire una classe delle persone, come segue: La classe delle persone così definita ha un attributo che è annodinascita che sarà sicuramente un numero intero ed un metodo che in base all'anno attuale passatogli calcola l'età della persona. Usando il formalismo di Java,per definire la classe persone scriveremo: Come si vede abbiamo dichiarato sia il metodo che l'attributo come public, vedremo tra poco cosa significa, vediamo anche che la classe comincia con { e finisce con }, così anche i metodi. 122 CAP. 6 – TECNOLOGIE SOFTWARE Questo ricorda molto il C, e devo dire che la sintassi di Java è molto simile, anzi quasi uguale a quella del C, mentre per chi non conosce il C, le parentesi graffe rappresentano il begin e l'end del pascal. La classe avrà un cosiddetto costruttore (o più di uno), che è un metodo particolare che di solito viene utilizzato per inizializzare gli attributi quando viene instanziata la classe in un oggetto, esso è una funzione che non ha nessun tipo di ritorno ed il nome uguale al nome della classe. Ho detto che i costruttori possono essere più di uno, però il nome del costruttore deve essere lo stesso di quello della classe. Chi è abituato a programmare con linguaggi non orientati agli oggetti troverà tutto questo strano, però è possibile perché Java fa il cosidetto overloading di funzioni, ovvero funzioni con lo stesso nome che hanno parametri diversi (detti in informatica parametri formali) sono diverse, e al momento dell'invocazione viene scelta la funzione in base al parametro (detto parametro attuale). Questo vale per ogni metodo, non solo per i costruttori. 123 CAP. 6 – TECNOLOGIE SOFTWARE Nell'esempio vediamo che ci sono tre costruttori, diversi per i parametri formali, che hanno lo stesso nome, vediamo inoltre un nuovo attributo che è Cognome, esso è una Stringa, definita come public String Cognome=new String(); la parte prima dell'uguale è chiara, lo è meno quella a destra, quel new String() crea un nuovo oggetto della classe String, e ne invoca il costruttore che non ha parametri, questo è il modo standard usato da Java per instanziare gli oggetti di una classe. Non deve sorprendere che il tipo di dato stringa sia una classe, in Java è possibile usare oggetti che rappresentano tutti i tipi di dato del linguaggio, inseriti per completezza del linguaggio, detti involucri che a volte sono molto utili, è però possibile anche usare i valori. Quindi ad esempio ci troveremo a lavorare sia con interi che con oggetti che rappresentano interi. Un’ultima cosa che salta all'occhio dall'esempio è che i costruttori hanno volutamente dei parametri che hanno lo stesso nome degli attributi, anche questo è possibile in Java, il quale stabilisce che quando c'è un assegnamento alla sinistra dell'uguale ci deve essere l'attributo, e alla destra il parametro, comunque se non vogliamo confonderci possiamo usare il riferimento this, scrivendo ad esempio this.annodinascita intendiamo l'attributo. 124 CAP. 6 – TECNOLOGIE SOFTWARE This è un riferimento all'oggetto, e nell'esempio lo troviamo anche come invocazione di funzione this(0), in questo caso esso è un riferimento ad un costruttore dell'oggetto, in questo caso chiama il costruttore persone (int annodinascita), con il valore 0. È quindi possibile in un costruttore chiamare un costruttore diverso della classe stessa, a patto che l'invocazione sia la prima istruzione del costruttore e che il costruttore sia diverso da quello attuale. A questo punto siamo pronti a creare oggetti appartenenti alla classe da noi appena definita, abbiamo tre modi per farlo, perché abbiamo creato tre costruttori, essi sono: Introduciamo adesso degli attributi e dei metodi particolari, i cosidetti membri statici. Per come abbiamo definito i membri della classe non ci è possibile referenziare direttamente dalla classe attributi e metodi (persone.annodinascita è un errore), questo perché essi lavorano su una istanza della classe, ovvero su un oggetto, però a volte può essere utile scrivere metodi e attributi che possano essere invocati senza dover istanziare l'oggetto, ma direttamente dalla classe, per fare questo occorre dichiararli static, ad esempio: 125 CAP. 6 – TECNOLOGIE SOFTWARE Introduciamo adesso la relazione is_a tra classi, data una classe è possibile creare una nuova classe da questa facendo come si dice in gergo una specializzazione della prima classe. La nuova classe creata è in relazione is_a con la prima. Creata una classe studente dalla classe (detta superclasse) persone, la nuova classe eredita dalla prima tutti i metodi e gli attributi, con la possibilità di definirne dei nuovo o di ridefinirne alcuni, in Java l'estensione di una classe si esplicita con la parola chiave extends. 126 CAP. 6 – TECNOLOGIE SOFTWARE Come si vede dall'esempio la classe studente eredita tutti i metodi e gli attrubuti della classe persone, definisce un nuovo attributo matricola e nei suoi costruttori chiama i costruttori della classe persone, con super(). super() può essere, come this(), una invocazione di un altro costruttore (tra parentesi vanno i parametri eventuali) o un riferimento alla classe (alla superclasse in questo caso), quindi super.annodinascita rappresenta l'attributo annodinascita della superclasse persone. Le relazioni is_a e instance_of sono le due relazioni più importanti dei modelli ad oggetti. I package sono delle collezioni di classi, racchiuse in una collezione che le accomuna. Sono in pratica delle librerie a cui l'utente può accedere e che offrono varie funzionalità. I package possono anche essere creati dall'utente, ad esempio racchiudendovi tutte le classi che ha definito per svolgere alcune funzioni che poi userà in vari programmi, ma questo a noi non interessa, perché ci interesserà vedere i package sicuramente più interessanti definiti in Java. È questa la vera potenza odierna di Java, il numero di classi già definite che svolgono i più svariati compiti, ed è anche la parte che continua sempre di più a crescere e ad aggiornarsi con le nuove versioni di Java (JDK 1.3 ne ha ben 18Mb). Il nucleo del linguaggio Java contiene solo le parole chiave per la costruzione delle classi, i commenti, i normali costrutti if, switch, while, do-while, for, etichette, break, continue e return (manca il goto), tutto il resto è implementato nei package del linguaggio, comprese le normali primitive di Input e di Output. In questo paragrafo vedremo la lista dei packages di Java e ne vedremo uno in particolare, quello che ci interessa vedere per scrivere la nostra prima applicazione Java ancor prima di avere visto i costrutti, ovvero quello in cui possiamo trovare le istruzioni di input e output. Sembrano pochini in effetti, sembra quasi che io abbia detto un stupidaggine in riferimento alla potenza di Java, ma se pensate che solo il package java.io comprende 50 classi e 10 interfacce capite bene che quelli di sopra sono una collezione di classi corposa. A questo punto vorremmo fare l'input e output da console, per fare questo dobbiamo usare il package java.lang . 127 CAP. 6 – TECNOLOGIE SOFTWARE Per usare un package in una nostra classe, prima della definizione della classe dobbiamo inserire l'istruzione import, ad esempio volendo usare il package java.awt dobbiamo inserire all'inizio del nostro file: import java.awt.*; La * sta ad indicare che vogliamo usarne tutte le classi, se invece vogliamo usarne solo una classe possiamo specificarlo, ad esempio, import java.awt.Frame; potremo usare solo la classe Frame dell'awt. Nel caso nostro, in cui vogliamo fare una operazione di output, dovremmo dichiarare all'inizio import java.lang.*; oppure, sapendo che la classe del package java.lang che contiene i metodi per fare questo è System potremmo scrivere : import java.lang.System; La classe System a sua volta avrà al suo interno una import java.io (che è il package per l'input e l'output) per accedere alle classi dell'input e dell'output, e le userà per mandare quello che vogliamo su schermo. Abbiamo visto un esempio di package che al suo interno invoca un altro package per fargli svolgere dei compiti, in queste librerie Java accade spesso questo, ed è proprio questo fenomeno che a molti fa apparire Java un linguaggio ostico, però superato questo blocco psicologico di fronte a quest'aspetto del linguaggio, la programmazione diviene semplice ed immediata. Abbiamo introdotto il package java.lang, vi dico anche che questo è il più importante di Java, in questo sono racchiuse le classi fondamentali del linguaggio, tanto che non serve dichiarare l'import, perché java lo importa automaticamente. Inoltre bisogna soffermarci su un aspetto fondamentale dell'importare i package, se noi importiamo nel mio file il package java.lang, anche se esso importerà il package java.io, io dal mio file non potremmo usare le classi di java.io, per farlo devo importarlo esplicitamente. Questo succede anche se programmiamo una applicazione in più file (con più classi), in ogni file dobbiamo importare i package che ci occorrono per la classe che stiamo definendo, non basta importarli in una sola. 128 CAP. 6 – TECNOLOGIE SOFTWARE 6.1.1 Le Servlet La crescente richiesta di pagine web con contenuti dinamici e di servizi su web, ha portato allo sviluppo di una particolare tipologia di software che collabora con il server web per estenderne le funzionalità e poter interagire con basi di dati. Le tecniche per realizzare questo tipo di software, sono tante, tra cui le più conosciute sono sicuramente le estensioni CGI (Common Gateway Interface), realizzate principalmente in C o in Perl. Anche Java mette a disposizione una API, le Servlet, appunto, che permette di sviluppare applicazioni lato server. Daremo una descrizione di tipo generale su questa tecnologia che si è rivelata molto migliore delle tecniche precedenti sotto molti aspetti quali la portabilità e l'efficienza. Fig. 6.2 – Java based Web Application Technology. Che cos'è una Servlet? Le Servlet sono moduli software scritti in Java che vengono eseguiti in applicazioni lato server per esaudire le richieste dei client. 129 CAP. 6 – TECNOLOGIE SOFTWARE Esse non sono legate ad un particolare protocollo per la comunicazione tra client e server, anche se più comunemente si utilizza il protocollo HTTP ed infatti si parla di http Servlet. Per scrivere una Servlet si fa uso delle classi del package javax.servlet che è il framework di base per la scrittura delle servlet e del package javax.servlet.http che è l'estensione del framework di base, per la comunicazione via http. Utilizzando un linguaggio portabile come Java, le Servlet consentono di realizzare soluzioni per estendere le funzionalità dei server web, indipendenti dal sistema operativo su cui esse vengono eseguite. Per cosa vengono utilizzate? Le Servlet vengono più comunemente utilizzate per: elaborare e salvare dati provenienti da form HTML; provvedere alla creazione di pagine HTML dinamiche, ad esempio utilizzando i dati contenuti in un database, in seguito ad una richiesta di un client; gestire informazioni con stato, ad esempio la gestione di un sistema di commercio elettronico, dove un certo numero di clienti fa degli acquisti contemporaneamente e dove occorre quindi mantenere in modo corretto le informazioni sui clienti e sui loro acquisti (il classico carrello della spesa); Servlet vs CGI Le Servlet hanno diversi vantaggi rispetto al tradizionale CGI e precisamente sono più efficienti, più facili da utilizzare, più potenti, più portabili e più economici. Vediamo più in dettaglio ciascun punto: Efficienza: Con una tradizionale applicazione CGI, viene generato un processo (istanza del programma o script CGI) per ogni richiesta che arriva al server, questo tipo di operazione può risultare abbastanza pesante in termini di risorse. Con le Servlet invece, la JVM (Java Virtual Machine) genera, per ogni richiesta da esaudire, un Thread Java, molto più leggero (lightweight) di un processo generato dal sistema operativo: con il CGI se ci sono N richieste contemporanee, esistono N immagini in memoria del programma CGI. 130 CAP. 6 – TECNOLOGIE SOFTWARE Con le Servlet invece, ci sono N Thread ma una sola copia della classe Servlet in memoria. Inoltre c'è da dire che l'efficienza è ancora superiore se si pensa che, ad esempio, un'applicazione CGI che si interfaccia con un database si connette ad esso ad ogni richiesta che arriva e si disconnette al termine: operazioni queste molto pesanti. Con le Servlet invece è possibile mantenere aperte una o più connessioni al database, utilizzando ad esempio una Connection Pool, e riutilizzarle da richiesta a richiesta. Facilità d'uso: Java mette a disposizione una API per la scrittura delle servlet che facilità molto le varie operazioni coinvolte nell'utilizzo di una Servlet e cioè: manipolazione dei dati provenienti dai form HTML, lettura e gestione delle intestazioni (headers) delle richieste http, gestione dei Cookie e delle sessioni e molte altre cose utili. Potenza: Con le servlet si possono fare tante cose che con i programmi CGI sono difficili o addirittura impossibili da realizzare: le servlet possono dialogare direttamente con il server web facilitando l'utilizzo e la condivisione di dati (testi, immagini ecc.) . Inoltre le servlet facilitano operazioni come la session tracking, permettendo il mantenimento di informazioni tra una richiesta e un'altra, e di caching delle operazioni già eseguite in una richiesta precedente. Portabilità: Essendo scritte in Java mediate un'apposita API standard, le Servlet possono girare su qualsiasi piattaforma. Oggi le servlet sono supportate, direttamente o mediante plug-ins (servlet engines), dalla maggior parte dei server web in circolazione, commerciali e free. Convenienza. Molti server web che supportano le servlet sono free o comunque hanno un basso costo. Se si dispone già di un server web commerciale (di quelli cari!) che non supporta le servlet l'aggiornamento con appositi plug-ins per il supporto delle servlet è normalmente free. 131 CAP. 6 – TECNOLOGIE SOFTWARE Architettura di base e ciclo di vita di una Servlet Una Servlet, nella sua forma più generale, è un'istanza della classe che implementa l'interfaccia javax.servlet.Servlet, e cioè javax.servlet.GenericServlet; ma come abbiamo già detto quella più utilizzata è quella che usa il protocollo HTTP e che si costruisce estendendo la classe javax.servlet.http.HttpServlet. Vediamo adesso il tipico ciclo di vita di una Servlet. All'avvio, il server carica in memoria la classe Servlet ed eventualmente le classi utilizzate da questa, e crea un'istanza chiamando il costruttore senza argomenti. Subito dopo viene chiamato il metodo init(ServletConfig config). Qui avvengono le inizializzazioni delle variabili globali, procedura che viene fatta una sola volta durante l'intero ciclo di vita della Servlet, e viene caricato l'oggetto ServletConfigche potrà poi essere recuperato più tardi mediante il metodo getServletConfig(). Quest'ultima operazione viene eseguita nel metodo init della classe GenericServlet ed è per questo che in ogni classe che la estende, come lo è HttpServlet, all'inizio del metodo init c'è una chiamata al metodo della superclasse e cioè super.init(config). L'oggetto ServletConfig contiene i parametri della Servlet e il riferimento a ServletContext che rappresenta il contesto in cui gira la Servlet. Una volta inizializzata la Servlet, viene chiamato il metodo service (ServletRequest req, ServletResponse res) per ogni richiesta che arriva dai client; questo metodo viene chiamato in modo concorrente cioè più Thread possono invocarlo nello stesso momento. In casi particolari e cioè quando si lavora con risorse non condivisibili, è possibile implementare Servlet non concorrenti. Quando una Servlet deve essere arrestata, ad esempio se deve essere aggiornata o bisogna riavviare il server, viene chiamato il metodo destroy() nel quale vengono rilasciate le risorse allocate nel metodo init. Anche questo metodo viene chiamato una sola volta durante il ciclo di vita della Servlet. Conclusioni Possiamo concludere dicendo che, le Servlet sono uno strumento tra i più validi per le applicazioni che richiedono contenuti web dinamici; sono abbastanza semplici da sviluppare e consentono di eseguire operazioni che con le tecniche precedenti risultavano difficili, questo grazie alla possibilità di utilizzare tutte le API che Java mette a disposizione, che sappiamo essere numerose e varie. 132 CAP. 6 – TECNOLOGIE SOFTWARE 6.2 Service-Oriented Architecture Durante l’evoluzione della tecnologia dei Web service, abbiamo notato un pattern. Ogni volta che applichiamo le tecnologie degli Web service ad un problema di integrazione di applicazioni, emerge un pattern. Chiamiamo questo pattern, Architettura Orientata al Servizio, service-oriented architecture (SOA). SOA è un semplice concetto, che lo rende applicabile ad un ampia varietà di situazioni di Web service. Fig 6.3 - Service-oriented architecture (SOA). In ogni service-oriented architecture si individuano tre ruoli: un richiedente del servizio, un fornitore del servizio, e un registro del servizio: 1. un service provider è responsabile della creazione della descrizione del servizio, della pubblicazione della descrizione del servizio su uno o più service registry, and receiving Web service invocation messages from one or more service requestors. 133 CAP. 6 – TECNOLOGIE SOFTWARE Un service provider, quindi, può essere una qualsiasi società che mantiene un Web service rendendolo accessibili su un qualche rete. Si può pensare ad un service provider come al "lato server" di una relazione client-server tra un service requestor e il service provider. 2. un service requestor è responsabile della ricerca di una descrizione di un servizio pubblicato su uno o più service registry ed è responsabile dell’usare la descrizione di un servizio per collegare o invocare i Web service mantenuti dagli service provider. Qualsiasi utente di un Web service può essere considerato un service requestor. Si può pensare ad un service requestor come al "client side" di una relazione client-server tra un service requestor e il service provider. 3. il service registry è responsabile di mostrare le descrizione dei Web service pubblicate dai service provider e di permettere ai service requestor di ricercare la collezione di descrizioni dei servizi contenuti all’interno del service registry. Il ruolo del service registry è semplice: essere l’intermediario tra service requestor e service provider. Una volta che il service registry crea il collegamento, non è più necessario; il resto dell’interazione avviene direttamente tra il service requestor e il service provider con l’invocazione del Web service. Ciascuno di questi ruoli può essere svolto da un qualsiasi programma o nodo della rete. In alcune circostanze, un singolo programma potrebbe svolgere più ruoli; per esempio, un programma può essere un service provider, che fornisce un Web service a degli utenti come pure un service requestor, che usa Web service forniti da altri. Una SOA include inoltre tre operazioni: publish, find, and bind. Queste operazioni definiscono dei contratti tra i ruoli nella SOA: 134 CAP. 6 – TECNOLOGIE SOFTWARE 1. l’operazione di publish è un atto di registrazione del servizio o di avviso di servizio. Costituisce il contratto tra il service registry e l service provider. Quando un service provider pubblica le descrizioni dei suoi Web service sul service registry, rende noti i dettagli di quel Web service ad una comunità di service requestor. I dettagli attuali della API di publish dipendono da come è stato implementato il service registry. In alcuni semplici scenari o nel "direct publish", il ruolo service registry è svolto dalla rete stessa, l’operazione publish è semplicemente l’azione di spostare la descrizione del servizio nella struttura a cartelle di un Web application server. Altre implementazioni di service registry, come l’UDDI, definisce una implementazione molto sofisticata dell’operazione di publish. 2. L’operazione di find è il logico duale dell’operazione di pubblicazione. L’operazione di ricerca è il contratto tra un service requestor e un service registry. Con l’operazione di ricerca, il service requestor dichiara un criterio di ricerca, come il tipo di servizio, molti altri aspetti del servizio come le garanzie di qualità del servizio, e così via. Il service registry confronta il criterio di ricerca con la collezione di descrizioni di Web service pubblicati. Il risultato dell’operazione di ricerca è una lista di descrizioni di servizi che soddisfano il criterio di ricerca. Ovviamente, la sofisticatezza dell’operazione di ricerca varia con l’implementazione del ruolo di service registry. I Semplici service registry possono fornire un’operazione di ricerca niente di più complesso di una HTTP GET senza parametri. In questo caso l’operazione di ricerca ritorna sempre tutti gli Web service pubblicati sul service registry ed è compito del service requestor di stabilire quale descrizione di Web service corrisponde alle proprie esigenze. L’UDDI, ovviamente, fornisce delle capacità di ricerca estremamente potenti. 3. l’operazione di bind racchiude la relazione client-server tra il service requestor e il service provider. L’operazione di bind può essere abbastanza sofisticata e dinamica, come la generazione on-the-fly del proxy lato-client basato sulla descrizione del servizio, usato per invocare il Web service; o può essere un 135 CAP. 6 – TECNOLOGIE SOFTWARE modello molto statico, dove uno sviluppatore scrive a mano come l’applicazione client richiama un Web service. La chiave del SOA è la descrizione del servizio. È la descrizione del servizio che è pubblicata dal service provider sul service registry. È la descrizione del servizio che viene recuperata dal service requestor come risultato di un’operazione di ricerca. È la descrizione del servizio che dice al service requestor tutto quello che deve conoscere in modo da collegare o invocare il Web service fornito dal service provider. La descrizione del servizio indica quale informazione (se presente) è ritornata al service requestor come risultato di un’invocazione di uno Web service. 136 CAP. 6 – TECNOLOGIE SOFTWARE 6.2.1 Web-Services Fig 6.4 - Flusso procedurale di una chiamata ad un servizio web. Un Web Services è un insieme di standard di comunicazione che permettono a diverse applicazioni di scambiarsi dati e servizi applicative. Lo scenario ipotizzato è quello di un’applicazione che necessita, per espletare le sue funzioni, di una serie di servizi . Si vogliono reperire altrove questi servizi invece di svilupparli all’interno dell’applicazione stessa. 137 CAP. 6 – TECNOLOGIE SOFTWARE I Web Services non sono stati la prima formalizzazione di architettura distribuita ma rispetto alle precedenti questa architettura offre dei vantaggi che l’hanno fatta preferire alle altre: semplicità della specifica; utilizzo di tecnologie standard; ampio consenso da parte di diverse aziende (Microsof, Sun, IBM….), la presenza di tool che aiutano enormemente la creazione di nuovi servizi e la fruizione dei servizi esistenti. Tutto ciò ha portato all’adozione dei Web Services in diversi contesti. Come accade spesso, avere numerose implementazioni, sia di servizi che di strumenti per realizzarli, porta la specifica a diventare uno “standard di fatto”. Questo grazie a: 1. Semplicità della specifica. Più una specifica è semplice, minore è il tempo che trascorre tra il suo studio e la realizzazione di progetti concreti. Le tecnologie che stanno alla base dei Web Services sono molto semplici, intuitive e con poche regole di base. 2. Utilizzo di tecnologie standard. Tutte le tecnologie alla base dei Web Services sono standard (essenzialmente XML per la rappresentazione, XML schema per la validazione e Http per il trasporto anche se esso si può basare su qualsiasi altro protocollo. L’XML come scelta di base permette, inoltre, anche ad una persona di “guardare” i messaggi ed di intuirne il significato. 3. Ampio consenso da parte di diverse aziende. Microsoft è stata la prima azienda a proporre modalità di comunicazione basate su XML. Però ha avuto la lungimiranza di non mantenere proprietarie le specifiche ma di renderle pubbliche. Questo ha portato ad un crescente interesse all’affermarsi dei primi standard. 4. Presenza di tool. La loro presenza è una conseguenza dei punti precedenti ma è l’unico vero motivo che riesce a catalizzare una quantità sempre crescente di sviluppatori. 138 CAP. 6 – TECNOLOGIE SOFTWARE I Web Services sono un ottimo strumento dove l’interoperabilità è un requisito essenziale. Per altri contesti e soprattutto in quelli in cui si ha un completo controllo sulle tecnologie adottabili nelle applicazioni coinvolte, i Web Services non sono una scelta ottimale: la loro generalità implica un volume di traffico notevole e non ottimizzato e un carico computazionale significativo sia per la codifica che la decodifica dei dati. Fig. 6.5 - Stack di collegamento tra messaggio SOAP e protocollo di rete HTTP. Lo stack di collegamento rappresenta le tecnologie che determinano come un messaggio viene spedito dal richiedente del servizio al fornitore del servizio. La base dello stack è un protocollo di rete (Network Protocol). I Web Service possono essere basati su una varietà di standard, i protocolli di collegamento di Internet come HTTP o HTTPS, SMTP, FTP, e via dicendo, come pure sofisticati protocolli di livello enterprise come RMI/IIOP e MQSeries. Per la codifica dei dati (Data Encoding), i Web service usano l’XML. In aggiunta, un contenuto non XML può essere referenziato da Web service con messaggio invocato, permettendo la massima flessibilità nei tipi di dati usati nel messaggio. Per le specifiche dei dati, i Web service usano l’XML Schema. Questo include sia gli schemi nel contesto del messaging XML sia gli schemi conformi ad un set di regole predefinite, come le regole della codifica SOAP. 139 CAP. 6 – TECNOLOGIE SOFTWARE Costruito sopra gli strati di networking protocol e data-encoding sono gli strati di messaging XML. Per l’XML Messaging, i Web service usano il SOAP nel data encoding, nello stile di interazione e nelle variazioni di binding dei protocolli. SOAP è usato come un semplice approccio per inserire un messaggio XML in una busta. Il risultato è una base solida di standard per i Web service. Concettualmente al di sopra il meccanismo di SOAP enveloping è un meccanismo per estensioni dell’envelope chiamati SOAP header. Con i SOAP header, le estensioni ortogonali come una firma digitale possono essere associati con il corpo del messaggio contenuto all’interno del SOAP envelope. Gli strati di questo stack sono ben definiti, sia come protocolli di rete standard che come specifiche SOAP stesse. Lo stack è il più diffuso e più ampiamente supportato set di tecnologie per i Web service. A destra nella figura ci sono tre colonne verticali che rappresentano le tecnologie associate che coinvolgono più livelli dello stack di collegamento. La sicurezza, per esempio, può intervenire ad ogni livello (l’SSL a livello di protocollo di rete e le firme digitale a livello delle estensioni dell’envelope). È fuori di ogni dubbio che non avremmo mai un singolo standard che copra tutti gli aspetti della sicurezza di cui hanno bisogno i Web service. Le altre colonne verticali elencate includono la qualità del servizio e la manutenzione. Questi sono solo alcuni degli aspetti degli Web service che possono intervenire in più levelli dello stack di collegamento, ma non ci sono standard universalmente accettati. 140 CAP. 6 – TECNOLOGIE SOFTWARE 6.2.2 Protocollo SOAP SOAP nasce come uno standard aziendale, progettato per migliorare l'interoperabilità della multipiattaforma, frutto del lavoro congiunto di colossi quali Microsoft, DevelopMentor, IBM, Lotus Development, UserLand e Sun Microsystems. La comunicazione da applicazione ad applicazione su Internet e/o su Intranet ha impegnato tantissimo il popolo degli sviluppatori. La maggior parte delle soluzioni individuate tendono ad essere specifiche della piattaforma, non scalano molto bene, spesso richiedono molti round-trip tra il Client e il Server. Altre soluzioni a questo tipo di problemi sono DCOM, CORBA, ecc. Le stesse comunque, incontrano non pochi problemi nel passare attraverso i FireWall. Il protocollo SOAP riduce molti di questi problemi, la specifica completa di SOAP è disponibile sul Web site di Microsoft. Il protocollo SOAP fornisce un modo consistente e strutturato di trasporto dei dati e di chiamata dei metodi fra le potenziali applicazioni distribuite. L'esecuzione di questi servizi basati sul WEB necessita di numerosi componenti posti sui vari computer. Poiché questi sistemi comprendono molti computer, inclusi client, server di medio livello e DBMS, sono denominati sistemi distribuiti. Sistemi distribuiti Solitamente i sistemi distribuiti utilizzano due modelli di comunicazione: 1. Trasferimento di messaggi, 2. Richiesta/risposta. Il primo modello consente la comunicazione tra gli attori mediante lo scambio di messaggi che possono essere spediti in ogni momento, questo provoca un'azione da parte del destinatario del messaggio, che a sua volta viene "risvegliato" per eseguire l'azione associata. 141 CAP. 6 – TECNOLOGIE SOFTWARE L'elaborazione dei messaggi può essere: • Sincrona • Asincrona Sincrona quando, a fronte della spedizione del messaggio, il destinatario immediatamente inizia l'esecuzione dell'azione associata. Asincrona quando, tra trasmettitore/ricevitore è interposta una coda di messaggi, e solo quando il ricevitore richiede di riceverli in coda li elabora. Ciò può essere fatto anche dopo molto tempo rispetto all'invio del messaggio. Nel modello richiesta/risposta, la richiesta e la risposta sono unite e quindi si parla di sistema sincrono. La richiesta viene inoltrata da un'applicazione e questa, prima di continuare con l'elaborazione, attende i risultati. Il modello richiesta/risposta è utilizzato per consentire la comunicazione tra i componenti sui diversi computer attraverso le RPC (Remote Procedure Call). Attualmente i due standard più diffusi per l'attivazione remota di procedure sono DCOM (Distributed Component Object Model) e IIOP (Internet Inter-Orb Protocol). Sono entrambi efficaci, anche se non progettati appositamente per l'interoperabilità, quindi non è possibile richiamare da un client un componente su un server prima di conoscere lo standard utilizzato dal server e prima di avere impostato la security. Su intranet è possibile limitare il sistema all'utilizzo di una piattaforma di riferimento, non appena si opera su internet, di solito non è possibile utilizzare una piattaforma uniforme nell'intero sistema. A questo punto DCOM e IIOP non consentono più la comunicazione tra due componenti all'interno del sistema né consentono agli utenti di transitare all'interno di domini affidabili. Per politiche di security, viene bloccato dai Firewall il passaggio di stream binari da porte TCP/IP. SOAP rappresenta una soluzione a questi problemi, sfruttando la tecnologia WEB e la flessibilità e l'estensibilità di XML, permette inoltre di transitare all'esterno delle reti intranet, non procurando problemi ai Firewall. Lo standard SOAP non introduce nuovi concetti in quanto si basa su tecnologia già esistente. Attualmente utilizza il protocollo HTTP come protocollo di trasporto di messaggi richiesta/risposta ed è indipendente dalla piattaforma ponendosi inoltre ad uno strato indipendente dal protocollo di trasporto. 142 CAP. 6 – TECNOLOGIE SOFTWARE Teoricamente è possibile effettuare la richiesta utilizzando qualsiasi protocollo di trasporto ed avere la risposta con qualsiasi protocollo di trasporto. Un Package SOAP contiene informazioni che consentono di richiamare un metodo anche se nella specifica SOAP il nome del metodo stesso non viene definito. SOAP, inoltre, non gestisce il garbage-collector distribuito, il boxcarring dei messaggi, la protezione del tipo e HTTP bidirezionale. SOAP consente il passaggio dei parametri e dei comandi tra i client e i server HTTP indipendentemente dalle piattaforme e dalle applicazioni sul client e sul server. I parametri e i comandi sono codificati mediante XML. URI, URL Prima di iniziare a parlare di protocollo HTTP, SOAP ecc. è importantissimo introdurre il significato di alcuni termini, quali URL, URI, URN. Un URI (Uniform Resource Identifier) è semplicemente una stringa formattata che identifica univocamente una risorsa. Un URIs può essere espresso in due diversi modi, uno è URLs (Uniform Resource Locators) e URNs (Uniform Resource Names). Una URL codifica il protocollo necessario per localizzare la risorsa specificata. Una URN è indipendente dalla posizione e non implica alcun protocollo o meccanismo per localizzare la risorsa specificata. Una URL inizia con il prefisso che identifica il protocollo, lo scheletro di una URL è ( [] indica opzionale ): <host> indica l'indirizzo IP del server, <port> è il numero di porta TCP su cui è in attesa il server, se non è specificato nessuna porta per default si assume la porta 80, e il <path> è l'URI assoluto passato con Request-URI nell'intestazione della richiesta HTTP, se non viene specificato nessun path per default si assume "\" (root). 143 CAP. 6 – TECNOLOGIE SOFTWARE Una URN a differenza della URL è poco comprensibile, una URN è una stringa univoca (molto simile ad UUID). Non esiste un modo generico per deferenziare una URN per cercare la risorsa che identifica, la sintassi utilizzata per definire una URN è: <NID> è l'indentificatore del namespace, e <NSS> è la stringa che specifica il namespace, ad esempio una interfaccia di un componente COM può essere rappresentata dalla seguente URN: Le URN è il meccanismo preferito per riferirsi a risorse mantenendosi indipendenti dalla locazione della risorsa stessa, questo meccanismo è pesantemente utilizzato in XML, SOAP. HTTP come protocollo di trasporto È pratica comune usare DCOM o CORBA all'interno di un server farm ed usare http per entrare nel farm da una macchina client. HTTP è un protocollo RPC-like molto semplice da installare, ed è molto più semplice farlo "passare" attraverso i Firewall rispetto ad altri protocolli. Una richiesta http è tipicamente inviata ad un WebServer (ad esempio IIS, Apache, Tomcat) anche se un numero sempre più crescente di applicazioni supporta direttamente HTTP come protocollo nativo in aggiunta a DCOM e IIOP. Come DCOM e IIOP, lo strato HTTP comunica con il protocollo TCP/IP, la porta standard utilizzata è la 80, ma qualunque altra porta può essere utilizzata allo stesso scopo. Dopo aver stabilito una connessione TCP, il client spedisce un messaggio di richiesta HTTP al server,che gli risponde con un messaggio di risposta HTTP dopo aver elaborato la richiesta stessa. 144 CAP. 6 – TECNOLOGIE SOFTWARE Sia richiesta che risposta contengono un'arbitraria informazione PAYLOAD, tipicamente rappresetanta dalle intestazioni Content-Length e Content-Type. Di seguito è riportato un esempio di richiesta HTTP valida: Esempio di richiesta http Come si può notare, l'intestazione HTTP è rappresentata da testo, è molto semplice trovare eventuali problemi HTTP utilizzando uno sniffer o un tool testuale, ad esempio TELNET. La natura testuale di HTTP lo rende adattabile a qualsiasi ambiente di sviluppo Web-Based. La prima linea della richiesta HTTP contiene tre componenti: il metodo HTTP , la richiesta URI e la versione del protocollo. La IETF (Internet Engineering Task Force) ha standardizzato il numero dei possibili metodi HTTP, questi sono GET e POST. Il Metodo GET è utilizzato per la navigazione nel WEB, il metodo POST è comunemente utilizzato per lo sviluppo di applicazioni. I metodi GET/POST possono essere utilizzati indifferentemente per inviare informazioni dal client al server. La richiesta URI (Uniform Resource Identifier) è un token usato dai server HTTP per identificare il destinatario della richiesta (RFC2616). Il server HTTP dopo aver elaborato la richiesta, rimanda indietro al client una risposta. La risposta contiene lo stato che indica la buona o cattiva elaborazione della richiesta stessa. Un esempio di risposta HTTP è: 145 CAP. 6 – TECNOLOGIE SOFTWARE In questo caso, il server ritorna il codice 200. Con questo codice, si indica in modo standard HTTP la corretta elaborazione della richiesta. Nel caso in cui il server non è stato in grado di elaborare la richiesta, la risposta del server può essere ad esempio: Il server HTTP decide che la richiesta inviata al destinatario definita nella URI deve essere temporaneamente rediretta su una differente URI, la risposta ritornata dal server è: Questa risposta avverte il client che per essere soddisfatta la richiesta, questa deve essere reinoltrata alla nuova URI definita in Location. Per eventuali approfondimenti sui codici dello stato standard, si rimanda alla RFC2616. SOAP Fig 6.6 – Struttura di un messaggio SOAP. 146 CAP. 6 – TECNOLOGIE SOFTWARE SOAP viene codificato mediante l'utilizzo di XML tramite il modello richiesta/risposta usando come protocollo di trasporto HTTP. Un metodo SOAP è semplicemente una richiesta HTTP e una risposta alle specifiche di decodifica SOAP. Come CORBA /IIOP, SOAP non richiede che un oggetto specifico sia legato ad un dato end-point ma spetta allo sviluppatore decidere come mappare l'oggetto end-point su un oggetto presente sul server. L'end-point SOAP è una URL http che identifica il metodo destinatario dell'invocazione. Una richiesta SOAP è una richiesta HTTP- POST. Per indicare il metodo da invocare si usa l'intestazione HTTP SOAPMethodName, un esempio: In questa intestazione il nome del metodo è indicato dopo il segno # ed è add. Il payload HTTP di una richiesta SOAP è un documento di XML che contiene i valori [in] e [in,out] dei parametri del metodo. Questi valori sono codificati come elementi figli di un elemento distinguibile di chiamata, condiviso con il nome, l'URI del namespace e dell'interstazione HTTP di SOAPMethodName. L'elemento della chiamata deve comparire all'interno del messaggio standard SOAP composto da <Envelope> e <Body>, un esempio di richiesta minima di un metodo SOAP è riportata di seguito: 147 CAP. 6 – TECNOLOGIE SOFTWARE Nell'intestazione SOAPMethodName è inserito un elemento figlio dell'elemento <Body>, altrimenti la chiamata viene rifiutata. Ciò permette agli amministratori del firewall di realizzare filtri di chiamata a particolari metodi senza passare dal parser XML. Il formato di risposta di SOAP è simile a quello della richiesta. Il payload di risposta conterrà i parametri [out] e [in,out] del metodo messi come elementi figli di un elemento distinguibile della risposta. Il nome di questo elemento è lo stesso dell'elemento di chiamata della richiesta concatenato con il suffisso Response. Di seguito è riportato un esempio minimo di risposta: In questo caso l'elemento di risposta è chiamato methodResponse, che è il nome di metodo seguito dal suffisso di Response. Inoltre c'è da notare che l'intestazione del HTTP SOAPMethodName è assente. L'intestazione è richiesta soltanto nel messaggio di richiesta, non nella risposta. 148 CAP. 6 – TECNOLOGIE SOFTWARE DataType Ogni elemento di un messaggio SOAP è un elemento strutturale di SOAP, un elemento della root, un accessor, o un elemento indipendente. I soap:Envelope, soap:Body e soap:Header sono gli unici tre elementi strutturali di SOAP. La relazione base è descritta dal seguente frammento dello schema di XML: Dei quattro tipi di elementi di SOAP, gli elementi strutturali sono utilizzati per rappresentare le istanze dei tipi, o riferimenti a istanze di tipi. Un elemento root è un elemento distinto, discende direttamente dall'elemento <soap:Body> oppure dall'elemento <soap:Header>. L'elemento <soap: Body> ha esattamente un elemento root, questo può rappresentare sia la chiamata, sia la risposta che eventuali elementi di fault. Questo elemento root deve essere il primo elemento child di <soap:Body> e deve essere corredato del URI del namespace che deve corrispondere all'intestazione HTTP SOAPMethodName, o soap:Fault nel caso di un messaggio di fallimento dell'invocazione del servizio. L'elemento di <soap:Header> può avere più elementi root, di cui uno per l'estensione dell'intestazione connessa con il messaggio. Questi elementi root devono essere discendenti diretti di <soap:Header> ed i loro URI del namespace indicano l'estensione del tipo di dati utilizzati. 149 CAP. 6 – TECNOLOGIE SOFTWARE Gli elementi accessor sono usati per rappresentare i campi, le proprietà, o i membri del tipo di dati. Ogni campo tipo di dato avrà esattamente un elemento accessor nella relativa rappresentazione di SOAP. Per capire bene come si utilizzato gli elementi accessor, consideriamo la seguente definizione di classe Java: Serializzando mediante SOAP questa classe, abbiamo: Gli elementi accessor ivalue e lvalue sono chiamati semplici accessor perché corrispondono a tipi primitivi, e sono definiti nella 2°parte del W3X XML Schema (per ulteriori informazioni clicca qui). Questa specifica formalizza i nomi e le rappresentazioni dei tipi numerici, tipo data, tipo stringa, inoltre è un meccanismo per la definizione dei tipi primitivi nuovi usando il costrutto <datatype> all'interno di nuova definizione dello schema. La soluzione più semplice per inserire strutture complesse all'interno di una struttura, è quello di incapsulare il valore della struttura all'interno dell'elemento accessor, ad esempio consideriamo la seguente definizione di classe Java: 150 CAP. 6 – TECNOLOGIE SOFTWARE Come possiamo notare, all'interno della classe sono inseriti due oggetti precedentemente specificati, quindi, serializzando la classe avremo: In questo caso, i valori degli oggetti sono inseriti direttamente sotto i loro elementi accessor. Elementi Indipendenti In SOAP, un elemento indipendente, rappresenta una istanza di un tipo che si riferisce ad almeno un elemento accessor multireference. Tutti gli elementi indipendenti sono etichettati dall'attributo di <soap:id> ed il valore di questo attributo deve essere unico in tutto l'Envelope di SOAP. 151 CAP. 6 – TECNOLOGIE SOFTWARE SOAP definisce un attributo (soap:Package) che può essere applicato ad un elemento. L'attributo è usato per controllare dove gli elementi indipendenti possono essere codificati. Le regole di serializzazione di SOAP impongono che un elemento indipendente deve essere codificato come un discendente diretto di un elemento <soap:Header>, <soap:Body> oppure un elemento che è marcato come <soap:Package='true'>. Annotando un elemento come Package, si garantisce che l'elemento XML che codifica l'istanza è completamente self-contained e non ha multireference accessori ad elementi che sono esterni al package. Array Gli array in SOAP sono trattati come caso speciale compound type. Un array SOAP deve avere un Rank (dimensione) e una capienza. Un array viene trattato come un compound type, ogni elemento di array ha come subelement il nome e il tipo definito nel namespace-qualified. Consideriamo ad esempio la seguente definizione di un tipo COM IDL: una istanza di questo tipo viene serializzata come: 152 CAP. 6 – TECNOLOGIE SOFTWARE se gli oggetti sono marcati con l'attributo [ptr], la codifica sarà fatta mediante l'utilizzo dei multireference accessor, un esempio di questa codifica è di seguito riportata: Elemento FAULT Un elemento FAULT può contenere quattro elementi figli: faultcode, faultstring, faultactor e detail. I valori di codice attualmente disponibili sono: VersionMismatch: questo errore viene restituito quando la chiamata ha utilizzato uno spazio non valido MustUnderstand: quando il destinatario non ha riconosciuto un elemento XML ricevuto, che contiene un elemento con un tag mustUnderstand="true". 153 CAP. 6 – TECNOLOGIE SOFTWARE Client: classi di errore causate da informazioni improprie nel messaggio SOAP effettivo, questi errori rappresentano un problema che riguarda il contenuto del messaggio effettivo e indicano che il messaggio non deve essere inviato nuovamente senza modifica. Server: tali errori riguardano i problemi con il server e di solito non rappresentano problemi con il messaggio SOAP. L'elemento faultstring è una stringa non utilizzata dalle applicazioni ma utilizzata solo come Struttura richiesta SOAP. L'elemento faultfactor può fornire informazioni sugli elementi che hanno provocato l'errore nel percorso del messaggio SOAP, è una URI che identifica l'origine: se l'errore si verifica in un'applicazione che non è la destinazione finale del messaggio, l'elemento faultactor deve essere incluso, altrimenti non è necessario. L'elemento detail è necessario se i contenuti dell'elemento Body (SOAP) non possono essere elaborati, questo viene utilizzato per fornire informazioni sugli errori specifici dell'applicazione. Un esempio di risposta SOAP contenente un fault è proposto qui di seguito: 154 CAP. 6 – TECNOLOGIE SOFTWARE 155 CAP. 6 – TECNOLOGIE SOFTWARE 6.3 Application Server 6.3.1 Apache Tomcat Struttura di una applicazione web La nozione di applicazione web è stata formalizzata per la prima volta nelle specifiche delle servlet Java. Sebbene il concetto di applicazione web sia piuttosto ampio e dipendente dal contesto in cui viene esaminato, la definizione fornita nelle suddette specifiche risulta di portata sufficientemente generale. Dal punto di vista dello sviluppatore di applicazioni web basate su Java risulta particolarmente importante la standardizzazione della struttura di tali applicazioni e l'introduzione degli archivi WAR come strumento per il deployment delle applicazioni web. Una applicazione web è una gerarchia di file e directory disposti secondo uno schema standard. /webapp. Una applicazione web ha una propria directory radice (root). Il nome della cartella corrisponde a ciò che nella terminologia delle servlet viene chiamato context path (nel seguito supporremo che tale nome di tale cartella sia webapp). La directory radice contiene tutti gli altri elementi che compongono l'applicazione web. File HTML, JSP, ... La directory /webapp contiene i documenti HTML, le pagine JSP, le immagini e le altre risorse che compongono l'applicazione web. Tali file possono essere strutturati in directory esattamente come si farebbe per un sito web statico. /webapp/WEB-INF. All'interno della cartella root si trova una directory speciale, denominata WEB-INF. La funzione di questa cartella è quella di contenere file riservati, come ad esempio il file di configurazione dell'applicazione, web.xml. Per questo motivo le specifiche impongono che la cartella ed il suo contenuto debbano risultare inaccessibili per gli utenti dell'applicazione. 156 CAP. 6 – TECNOLOGIE SOFTWARE /webapp/WEB-INF/web.xml. Il file web.xml viene comunemente denominato deployment descriptor. Si tratta del file di configurazione dell'applicazione web; in esso, ad esempio, si definiscono gli alias delle servlet, i parametri di inizializzazione, le mappature dei percorsi e così via. /webapp/WEB-INF/classes e /webapp/WEB-INF/lib. Queste due directory sono destinate a contenere le classi e gli archivi Jar di cui la nostra applicazione web necessita. Se dobbiamo utilizzare delle classi Java compilate (file con estensione .class andremo a copiarle all'interno di /webapp/WEB-INF/classes, secondo l'usuale struttura di directory Java (così se abbiamo una classe MiaServlet contenuta nel package sito.servlet. il percorso del file compilato sarà /webapp/WEB- INF/classes/sito/servlet/MiaServlet.class). Se dobbiamo utilizzare classi contenute in archivi Jar, invece, sarà sufficiente copiarli in /webapp/WEB-INF/lib. Archivi WAR Una volta sviluppata una applicazione web possiamo "impacchettarla" in un archivio WAR (Web Application Archive). Un archivio WAR non è altro che un archivio Jar, una vecchia conoscenza dei programmatori Java, la cui estensione viene modificata in .war semplicemente per indicare che il contenuto dell'archivio è una applicazione web. Gli archivi WAR hanno una duplice funzione: oltre a quella ovvia di comprimere tutte le componenti di una applicazione in un unico archivio, costituiscono il formato di deployment dell'applicazione stessa. Il termine inglese deployment indica la messa in opera dell'applicazione. Uno scenario tipico è quello in cui l'applicazione viene sviluppata localmente per poi essere trasferita, ad ultimazione, sul server vero e proprio (detto anche di produzione). In questo caso è sufficiente creare il file WAR, copiarlo sul server di produzione e seguire le istruzioni per l'installazione del WAR relative al servlet container che si sta utilizzando. Nel caso di Tomcat, l'installazione di un WAR è estremamente semplice: è sufficiente copiare il file nella directory webapps e avviare (o riavviare) il server, che provvederà da solo a decomprimere l'archivio e ad avviare l'applicazione. 157 CAP. 6 – TECNOLOGIE SOFTWARE Un esempio di comando per la creazione di un archivio WAR (da digitare dopo essersi spostati all'interno della cartella webapp) è il seguente: jar cvf webapp.war È consigliabile, in ogni caso, fare riferimento alla documentazione ufficiale del tool jar per una spiegazione esaustiva delle opzioni disponibili. In questa breve nota abbiamo preso dimestichezza con la strutturazione di una applicazione web, così come definita nelle specifiche Servlet. Organizzando le nostre applicazioni in tal modo otterremo diversi vantaggi: • aumenteremo la portabilità dell'applicazione, rendendone più semplice la messa in opera; • renderemo l'applicazione più comprensibile ad altre persone, in quanto sarà molto più semplice sapere dove si trovano le classi, gli archivi Jar e le altre componenti dell'applicazione stessa; • potremo racchiudere l'intera applicazione in un archivio WAR, rendendone semplice l'installazione su tutti i servlet container conformi alle specifiche Sun. Abbiamo così compiuto il primo passo per la realizzazione di una applicazione web in ambiente Java, che abbiamo imparato a strutturare in modo standard. Il prossimo argomento da affrontare sarà la configurazione dell'applicazione attraverso il già citato file web.xml. L'ambiente di Tomcat Tomcat contiene al suo interno tutte le funzionalità tipiche di un web server, ovvero - in sintesi - ha la capacità di interpretare una richiesta di una risorsa veicolata su protocollo HTTP, indirizzarla ad un opportuno gestore (o prenderla dal filesystem) e restituire poi il risultato (codice HTML o contenuto multimediale che sia). 158 CAP. 6 – TECNOLOGIE SOFTWARE In questo aspetto non differisce molto da altri web server, come Apache, se non che spesso si rivela meno prestante. La caratteristica innovativa di Tomcat non è quindi quella di essere un veloce web server, ma piuttosto quella di fornire allo sviluppatore un vero e proprio ambiente nel quale girano applicazioni Java (le servlet). Adesso cercheremo di comprendere meglio come sia strutturato questo ambiente Java nel quale prenderanno vita le nostre applicazioni latoserver. Contenitori in Tomcat Come nelle normali applicazioni, anche nella programmazione lato server gli oggetti creati devono avere uno scopo, ovvero essere definiti ed accessibili in un determinato contesto. Utilizzare Tomcat equivale a suddividere lo spazio delle risorse in contenitori sostanzialmente indipendenti nei quali possono essere depositati oggetti Java, secondo una logica orientata al web. Per comprendere appieno questo concetto analizziamo nel dettaglio i singoli contenitori che sono tra loro strutturati in maniera abbastanza gerarchica. Tomcat Chiaramente il primo livello corrisponde al web server stesso che avrà un insieme di variabili ad esso associate. Ad esempio qui dentro vi sarà indicazione del numero di thread attualmente in esecuzione, della versione di Tomcat o altre proprietà globali generalmente di poco interesse nella programmazione. Contesto Quando un utente accede al web server accede in realtà ad una sezione specifica del web server (a un certo dominio virtuale o directory, ad esempio) identificata sostanzialmente dalla URL. Nel gergo di Tomcat la sezione viene chiamata contesto (context). All'interno di questo contenitore si troveranno quindi oggetti comuni a tutta la sezione, che saranno gli stessi per tutti gli utenti e tutte le applicazioni del contesto. 159 CAP. 6 – TECNOLOGIE SOFTWARE Questo contenitore viene generato all'avvio di Tomcat e rimane attivo indipendentemente dal fatto che qualcuno lo stia interrogando in quel momento. Questo non vuol dire che rimanga invariato, anzi, il suo contenuto cambierà in funzione delle richieste ricevute ed ogni elemento contribuirà a definire l'ambiente di tutta la sezione. Sessione Il primo contenitore con caratteristiche fortemente orientate al web è quello associato alla sessione (Session). Come dice il nome questo contenitore viene associato ad un utente (o, meglio, ad un client) per tutto il tempo per il quale rimane connesso ad un contesto specifico. Al suo interno verranno memorizzati oggetti che saranno accessibili solo a quell'utente e ne personalizzeranno l'ambiente rispetto ad altri client che utilizzino risorse dello stesso contesto nello stesso momento. Richiesta Il contenitore con la vita più breve è la richiesta (Request) che nasce e muore nell'ambito della singola transazione web. Raramente questo contenitore viene riempito da applicazioni anche se svolge un ruolo fondamentale nel flusso dei dati che attraversano Tomcat. Il flusso di dati Abbiamo visto che l'oggetto Context viene creato all'avvio di Tomcat mentre l'oggetto Request nasce muore ad ogni richiesta. Andiamo ad analizzare un po' più in dettaglio il flusso logico che segue Tomcat nel processare le singole richieste web che riceve. Richiesta di una risorsa Supponiamo che un client acceda a una risorsa su di un server su cui gira Tomcat. Innanzi tutto viene instanziato un oggetto Request, Req, in Tomcat nel quale vengono 160 CAP. 6 – TECNOLOGIE SOFTWARE inserite tutte le informazioni ricevute tramite HTTP (dalla url richiesta sino ai cookies) e "al suo fianco" viene instanziato un oggetto risposta (Response, Res) nel quale costruire pian piano la risposta da restituire al client. Leggendo la url all'interno della richiesta Tomcat è quindi in grado di comprendere a quale dei contesti residenti in memoria debbano essere consegnati questi due oggetti Req e Res. Contesto e sessione Il contesto invocato da Tomcat provvederà a vedere se esiste già una sessione attiva per quel tipo di client leggendone la "firma" nella richiesta (sotto forma di cookie o nella url, a seconda del metodo usato). Se la sessione, Ses, esiste già tra quelle immagazzinate nel context, il contesto la riprende e la affianca agli oggetti Req e Res. A questo punto l'ambiente è stato completamente definito e il web server può passare il controllo all'applicazione associata alla risorsa in questione. Le Servlet A questo punto del percorso logico, il contesto è in grado di decidere (sulla base del suo file di configurazione) a quale applicazione passare il controllo all'interno dell'ambiente di lavoro definito in tutto il percorso (la più semplice delle applicazioni è chiaramente quella che si occupa di restituire un file presente sul disco del server). L'applicazione Java (la servlet) potrà quindi svolgere tutte le sue funzioni attingendo agli oggetti già presenti nei vari contenitori (nella sessione, ad esempio) o mettendocene di nuovi. Risposta Al termine del proprio lavoro la Servlet deve dare un esito al proprio lavoro tramite la risposta Res. Le uniche due modalità per farlo sono o riempirla con dei contenuti che il client sia in grado di comprendere (codice HTML, ad esempio) oppure inserire un ordine per il contesto di redirigere il controllo ad un'altra risorsa (forward). 161 CAP. 6 – TECNOLOGIE SOFTWARE Nel primo caso il contesto ripasserà tutto l'oggetto a Tomcat che si occuperà di generare l'output per il client. Nel secondo caso, se la risorsa è esterna al contesto il controllo verrà restituito a Tomcat che ricomincerà il percorso logico con questa nuova risorsa. Se invece la risorsa è interna al contesto un'operazione di forward equivale a fare un passo indietro nel percorso logico per poi tornare avanti su un altro sentiero o, in altri termini, chiamare la Servlet associata alla risorsa indicata nell'istruzione di forward, passandole nuovamente tutto l'ambiente. 162 CAP. 6 – TECNOLOGIE SOFTWARE 6.4 Strumenti di sviluppo 6.4.1 Apache Axis Axis è un progetto della Apache Software Foundation e prende origine dal progetto Apache SOAP: durante lo sviluppo di quest’ultimo è nata l’esigenza di una riscrittura dell’intero progetto per farlo evolvere ad una architettura maggiormente modulare e con un meccanismo di parsing XML di tipo SAX. Axis è un SOAP engine: questo significa che è un framework che si concentra unicamente sulle problematiche della creazione di client e server e per la gestione di messaggi SOAP; in pratica consiste in un insieme di tool per la generazione automatica di classi e in una libreria che “incapsula” in classi Java l’accesso alle tecnologie connesse ai Web Services. L’architettura generale di Axis appare nella seguente figura nei suoi componenti principali. Fig. 6.7 – Architettura generale di Axis. Il requestor è un client che effettua una richiesta su alcuni dei protocolli supportati da Axis. Generalmente è usato HTTP. Il requestor può essere una desktop application, una web application, o un altro web service. Il motore Axis agisce agevolando la comunicazione tra client e web service maneggiando la traduzione ad e da web service standard. 163 CAP. 6 – TECNOLOGIE SOFTWARE Axis permette allo sviluppatore di definire una serie di handlers, allacciati alla richiesta o alla risposta. Questi handlers sono simili a filtri servlet; ogni handler svolge uno specifico compito adando avanti fino al prossimo handler in linea. Gli handlers si adattano insieme in una catena , la quale comprende un set specifico di handlers che corrispondono e richieste o risposte ad un web service. Questo processo è mostrato in figura. Fig. 6.8 – Catena degli handler per le risposte e le richieste. Esempi di handlers sono componenti di sicurezza, sistemi di jogging, e trasformazioni. Un speciale handler , conosciuto come il pivot point handler, esiste per ogni web service. Questo handler elabora le chiamate attuali dei metodi del web service . In altre parole , questo si ha dove il contenuto definito dalla chiamata del metodo come un servizio web è spedito indietro al client richiedente. Le catene di handler sono definite in documento di configurazione usato dal motore di Axis chiamato server.config. Questo file è un documento XML che definisce i parametri di configurazione per Axis. Axis è composto da: Una web application che si occupa di gestire l’ambiente di esecuzione dei servizi (routine, istance poooling, serializzazione e deseralizzazione dei messaggi SOAP, ecc….); Una API composta da classi di utilità per la scrittura di servizi web e da classi necessarie al funzionamento della web application e dei tool; 164 CAP. 6 – TECNOLOGIE SOFTWARE Una seri di tool, tra cui WSDL2Java per generare scheletri lato server e stub lato client dei servizi web a partire dalla descrizione WSDL; Java2WSDL per generare la descrizione come servizio web di una classe Java; Diversi tool per l’amministrazione e la gestione dei servizi installati; Un TCP monitor stand-alone ed un SOAP monitor integrato nella web application per controllare la forma dei messaggi scambiati tra i servizi nelle fasi di debug e test. Tra le caratteristiche più interessanti di Axis c’è la possibilità di creare web service in maniera immediata a partire da classi Java molto semplici con estensione .jws(Java Web Service). Axis può essere quindi utilizzato in una serie di scenari anche molto diversi tra loro, ad esempio può servire per: la creazione di applicazioni client di servizi web già esistenti per i quali è disponibile il WSDL: utilizzando WSDL2Java si possono creare in maniera automatica gli stub per l’accesso a servizi esistenti implementati con qualsiasi piattaforma . Le applicazioni client che utilizzano gli stub non necessitano di ambienti di esecuzione particolari ma soltanto della presenza della libreria axis.jar nel classpath; la comunicazione via JAX-RPC tra processi Java: le API di Axis implementano una versione JAX-RPC, rendendo possibile lo sviluppo di applicazioni distribuite Java con protocollo di trasporto SOAP; la creazione di servizi web a partire da classi java: Axis offre diversi meccanismi per l’implementazione dei servizi. Quello più semplice e completamente trasparente per il programmatore è JWS , ma sono disponibili anche con modelli di servizi più complicati dove è possibile personalizzare , ad esmpio , le modalità di serializzazione dei messaggi , la struttura dei package ed il formato dei parametri , senza mai occuparsi della descrizione WSDL o del formato SOAP dei messaggi , grazie all’integrazione tra l’ambiente di esecuzione e Java2WSDL; 165 CAP. 6 – TECNOLOGIE SOFTWARE l’implementazione di servizi web a partire da descrizioni WSDL: il tool WSDL2Java è particolarmente utile quando si parte dalla descrizione dei servizi per la realizzazione di un sistema piuttosto che della loro implementazione. 166 CAP. 6 – TECNOLOGIE SOFTWARE 6.5 Database Relazionale 6.5.1 Oracle ⇒ L' architettura di Oracle Un server Oracle è rappresentato fondamentalmente da due strutture, il database e l'istanza. Con il termine database (d'ora in poi DB) si indicano i file fisici in cui sono memorizzati i dati, mentre per istanza si intende l'insieme delle aree di memoria e dei processi di background necessari ad accedere ai dati, ovvero al DB. L'architettura del server è complessa: ogni area di memoria nell'istanza contiene dati che non sono contenuti in altre e i processi di background hanno compiti ben precisi, tutti diversi fra loro. Ogni DB deve obbligatoriamente fare riferimento almeno ad un'istanza, è anche possibile avere più di un'istanza per database, ma in realtà faremo sempre riferimento a database a singola istanza. Ciascun DB consiste di strutture logiche di memorizzazione, per immagazzinare e gestire i dati, (tabelle, indici, etc.) e di strutture fisiche di memorizzazione che contengono le strutture logiche.I servizi offerti dalle strutture logiche del server sono indipendenti dalle strutture fisiche che le contengono. Questo perché le strutture logiche possano essere progettate nello stesso modo indipendentemente dall'hardware e dal sistema operativo impiegati.Quindi sia che abbiamo un'installazione di server Oracle su sistema operativo Microsoft, Linux o Solaris non troveremmo alcuna differenza nella progettazione delle strutture logiche di memorizzazione. ⇒ Strutture logiche di memorizzazione Tablespace Al vertice della scala gerarchica troviamo i Tablespace, strutture che raggruppano, a loro volta, quelle di livello più basso. È ammissibile suddividere i dati in differenti tablespace in base ad uno specifico significato logico dettato dalla nostra 167 CAP. 6 – TECNOLOGIE SOFTWARE applicazione che interagirà con il database. Per esempio si può creare un tablespace per ciascun utente che andrà a memorizzare propri dati nel database. Questa suddivisione logica ha l'enorme vantaggio di consentire l'amministrazione di una porzione limitata del DB, ovvero di un tablespace, senza intaccare la funzionalità delle parti rimanenti. Ogni database deve avere uno o più tablespace. Come requisito minimo per la creazione di un DB Oracle crea sempre un tablespace di sistema, denominato SYSTEM. Block Un blocco dati è la più piccola unità di memorizzazione in Oracle, pertanto indivisibile, e corrisponde ad un numero di byte scelto dal DBA durante la creazione del database. È sempre multiplo della capacità del blocco usato dal sistema operativo su cui si opera. Per approfondire è consultare la documentazione di Oracle alla voce DB_BLOCK_SIZE. Extent È composto di un numero specifico di blocchi contigui di dati (block). Segment È formato da un insieme di extent. Ne sono un esempio le tabelle o gli indici. Ogni qualvolta si crea un segment Oracle alloca al suo interno almeno un extent che, a sua volta, contiene almeno un block. Tutto questo è sempre deciso dal DBA. Un segment può essere associato esclusivamente ad un tablespace. 168 CAP. 6 – TECNOLOGIE SOFTWARE Figura 6.9 - Relazioni tra tablespace, segment, extent e block ⇒ Strutture fisiche di memorizzazione Data file File che contengono tutti i dati del DB. Ogni database Oracle deve avere uno o più data file. Ciascun data file è associato esclusivamente ad un tablespace, ma un tablespace può essere formato anche da più di un data file. Ne esiste sicuramente almeno uno per il tablespace SYSTEM. Redo log file Registrano tutte le modifiche occorse ai dati. Ogni DB possiede almeno due file di redo log, perché Oracle scrive in questi file in maniera circolare: quando un file di redo log è pieno allora Oracle scrive in quello successivo, quando l'ultimo file di redo log è pieno allora Oracle ricomincia dal primo, assicurandosi però di memorizzare le informazioni nei data file prima di sovrascriverle. 169 CAP. 6 – TECNOLOGIE SOFTWARE Se una qualsiasi anomalia non permette la scrittura delle modifiche occorse al database nei rispettivi data file, allora possiamo tranquillamente ottenere tali modifiche dai redo log file. Le modifiche ai dati, pertanto, non sono mai perse. I redo log file rappresentano la cronologia delle modifiche ai dati e sono di vitale importanza per l'integrità del DB. Oracle permette di avere più di una copia per ciascun redo log file: questa importante caratteristica è denominata multiplexing dei redo log file. Control file Ogni database ha almeno un control file che contiene informazioni circa la struttura fisica del DB, ovvero il nome, la data e l'ora di creazione e il percorso completo di ciascun data file e redo log file. È di vitale importanza e si consiglia di configurarne più di una copia: anche in questo caso parleremo di multiplexing di control file. Figura 6.10. Relazioni fra le strutture fisiche e logiche di un DB 170 CAP. 6 – TECNOLOGIE SOFTWARE ⇒ Aree di memoria in Oracle Le aree di memoria di un server Oracle sono usate per contenere i dati, le informazioni del dizionario dei dati, i comandi SQL, il codice PL/SQL e tanto altro ancora. Tali aree sono allocate nell'istanza Oracle ogni qualvolta questa è fatta partire e deallocata, vale a dire rilasciata, quando la stessa è "terminata". Le due maggiori strutture di memoria sono la System Global Area (SGA) e la Program Global Area (PGA). Figura 6.11 - Componenti della SGA e della PGA System Global Area È un'area di memoria condivisa, il che significa che tutti gli utenti del DB ne condividono le informazioni. È composta a sua volta di più aree di memoria ed ha uno spazio allocato all'avvio di un'istanza definito dal parametro SGA_MAX_SIZE. L'SGA e i processi di background formano l'istanza Oracle. Come si può vedere in figura 3 quest'area è formata dal Database Buffer Cache, dal Redo Log Buffer, dallo 171 CAP. 6 – TECNOLOGIE SOFTWARE Shared Pool, dal Large Pool e dal Java Pool. Le ultime due sono opzionali mentre le altre sono obbligatorie per ciascuna istanza. ⇒ I processi di background di Oracle Un processo è un meccanismo usato dal sistema operativo per eseguire alcune attività. Oracle inizializza diversi processi di background per ogni istanza. Ogni processo di background è responsabile nel portare a termine specifici compiti. Non tutti i processi sono presenti in un'istanza Oracle: la maggior parte di essi sono obbligatori, la presenza di altri dipende dal tipo di architettura Oracle desiderata. Sono processi di background il Database Writer (DBWn), il Log Writer (LGWR), il Checkpoint (CKPT), il System Monitor (SMON), il Process Monitor (PMON), l'Archiver (ARCn), il Recoverer (RECO), il Dispatcher (Dnnn) e lo Shared Server (Snnn). Per la realizzazione del progetto è stato utilizzato un database Oracle 10G Express. 172 CAP. 6 – TECNOLOGIE SOFTWARE 6.5.2 FreeTOAD FreeToad è un tool software free che permette di visualizzare e modificare attraverso un interfaccia grafica il contenuto informativo di un database. Esso mette a disposizione diversi strumenti grafici per la manipolazione di database, tabelle, campi e dati e un prompt dei comandi con il quale, attraverso del codice SQL, è possibile interrogare una base di dati. Per prendere confidenza con esso, parallelamente al progetto JTelemed, è stato realizzato un semplice database di tutti i comuni italiani. Di seguito alcune immagini del software freeTOAD. Elenco Tabelle di un determinato DB. Ho selezionato la tabella A_ITTCOMUNI_TUTTI Records della tabella A_ITTCOMUNI_TUTTI Figura 6.12 – Records di una tabella visualizzati attraverso freeTOAD 173 CAP. 6 – TECNOLOGIE SOFTWARE Figura 6.13 – Campi della tabella A_ITTCOMUNI_TUTTI Figura 6.14 – Risultati di una query SQL 174 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI Illustrazione delle problematiche più critiche incontrate durante la realizzazione del progetto e dei possibili miglioramenti da apportare per sviluppi futuri. INDICE ARGOMENTI: 7.1 Il server Linux 7.2 Gestioni critiche 7.3 Un database Open Source: MySQL 175 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI 7.1 Il server Linux Come detto nel capitolo 5.3 nella descrizione della fase di deploy, “le macchine di sviluppo, soprattutto se si utilizzano ambienti di sviluppo molto sofisticati, sono configurate diversamente da quelle di test, pertanto il passaggio da un ambiente all'altro potrebbe non essere indolore”. Nel nostro caso il server di sviluppo è una semplicissima macchina con piattaforma Windows nella quale abbiamo istallato tutti gli strumenti per la realizzazione del Web service (tomcat, axis, eclipse) mentre la macchina di test, quella che effettivamente è il server e che permette la pubblicazione sul web, gira su un sistema operativo Linux. Nonostante siano state prese tutte le dovute precauzioni in fase di programmazione, soprattutto nella gestione delle path di file e di directory, qualche piccolo, ma fondamentale aspetto rendeva le due fasi (di sviluppo e di test) non completamente dipendenti e perciò nel passaggio alla fase di test ogni volta bisogna avere l’accortezza e la pazienza di tornare sul codice. Vediamo brevemente di cosa si tratta. PRECAUZIONI: La disponibilità di implementazioni della JVM (Java Virtual Machine) per diversi ambienti operativi è la chiave della portabilità di Java, proclamata nello slogan write once, run everywhere ("scrivi una volta, esegui dappertutto"). La macchina virtuale realizza infatti un ambiente di esecuzione omogeneo, che nasconde al software Java (e quindi al programmatore) qualsiasi specificità del sistema operativo sottostante. Ciò ha permesso di non dover andare a modificare metodi e funzioni specifiche e soprattutto di poter definire univocamente una delle questioni più delicate nella gestione di files: le path. La grande maggioranza dei servizi implementati si basa sui due seguenti passi: • Creazione di un file .xml tramite una query SQL; • Invio del file appena creato; 176 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI Il file xml viene salvato fisicamente sul file system nella cartella temp dell’Application Server (il tomcat). Onde evitare incompatibilità tra i vari sistemi operativi definiamo tale percorso come: Path=System.getProperty("catalina.home")+File.separator+"temp"+File.separator; Che corrisponde: WINDOWS LINUX C:/TOMCAT554/temp/ /var/jakarta-tomcat-5.5.4/temp/ System.getProperty("catalina.home") restituisce il valore della variabile di ambiente CATALINA HOME impostata in fase di istallazione dell’Apllication Server mentre il File.separator inserisce il carattere di separazione della path assoluta di un file (slash per Linux, back-slash per windows). Questo è stato un semplice esempio di portabilità di java in quanto siamo riusciti a passare da windows a linux senza dover effettuare nessun cambiamento. Purtroppo però le cose non vanno sempre così, infatti in fase di attachment: //Invio del file xml ottenuto dalla query come allegato message=(org.apache.axis.MessageContext.getCurrentContext()).getResponseMes sage(); /*VERSIONE PER LINUX*/ message.addAttachmentPart(message.createAttachmentPart(new DataHandler(new URL("file:"+File.separator+File.separator+fileNamePath+fileName)))); /*VERSIONE PER WINDOWS*/ message.addAttachmentPart(message.createAttachmentPart(new DataHandler(new URL("file:"+File.separator+fileNamePath+fileName)))); Come si può notare dal frammento di codice i due sistemi operativi si comportano in modo differente nella gestione dell’oggetto URL. La sintassi in questione è: 177 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI file: Protocollo // FilePath+FileName Doppio File.separator Nome del file L’ingruenza tra i due sistemi sta nel fatto che windows accetta una sintassi con un solo file separator, mentre linux una sintassi con due file separator. Risultato di ciò è che se non si accetta questa predisposizione si ha un errore in compilazione. Un altro aspetto di fondamentale importanza sempre riguardo all’utilizzo di due sistemi operativi differenti è la gestione degli attachments. Dopo un lungo studio e una lunga fase di test abbiamo imparato che quando la dimensione dell’allegato al messaggio SOAP supera una certa soglia il sistema operativo si fa carico di prendere tale allegato e salvarlo temporaneamente sotto una sua ben specificata directory per poi poterlo inviare al destinatario. Il percorso di questa directory è specificato in un file di configurazione, server-config.wsdd che viene creato, lato server, automaticamente dall’eclipse in fase di generazione del Web service. Leggendo le righe di codice di questo file, ad un certo punto si incontra il seguente frammento: <globalConfiguration> <parameter name="sendMultiRefs" value="true"/> <parameter name="disablePrettyXML" value="true"/> <parameter name="adminPassword" value="admin"/> <parameter name="attachments.Directory" value="C:\workspace\.metadata\.plugins\org.eclipse.wst.server. core\tmp0\webapps\jtelemed\WEB-INF\attachments"/> <parameter name="dotNetSoapEncFix" value="true"/> 178 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI Facendo un deploy dell’intero progetto come war sul server linux anche il file server-config.wsdd viene importato con tutte le sue caratteristiche e soprattutto con la sua attachments.Directory impostata con una path valida sotto windows ma non sotto linux: occorre definire una nuova path: <globalConfiguration> <parameter name="sendMultiRefs" value="true"/> <parameter name="disablePrettyXML" value="true"/> <parameter name="adminPassword" value="admin"/> <parameter name="attachments.Directory" value="/var/jakarta-tomcat5.5.4/webapps/jtelemed_server/ WEBINF/attachment"/> <parameter name="dotNetSoapEncFix" value="true"/> 179 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI 7.2 Gestioni critiche Un’aspetto che merita di essere citato come gestione critica è il processo di cancellazione dei files creati sia lato server che lato client, files che sono parte integrante della comunicazione all’interno del nostro Web Service. Come ormai ben saprete, il nostro server risponde alla richiesta di un servizio quasi esclusivamente generando un file che poi invierà come allegato al messaggio SOAP ovvero al messaggio di risposta. Questi files prima di poter essere spediti vengono salvati fisicamente sul file system nelle directory temp sotto tomcat (per il server) e nella directory temp sotto webapps/jtelemed (per il client). Per poter avere un’accurata gestione delle risorse è necessario prevedere un meccanismo di cancellazione di questi files. Attualmente è stato implementato una semplicissimo metodo all’interno della classe FileUtil che cerca di soddisfare le nostre necessità, ma con un elevato numero di files il sistema va in crisi. Non appena un file viene inviato al destinatario non si ha più bisogno di esso e deve essere eliminato; quindi alla fine di ogni servizio in cui sono interessati i files deve essere prevista una piccola gestione di questa procedura di cancellazione. Questo approccio però non è funzionante in quanto il sistema, per ancora oscuri motivi, non riesce fisicamente a cancellare il file appena creato e appena inviato. Un’alternativa a questo è stata rappresentatata dall’idea di cancellare, al momento della creazione di un nuovo file, il file precedente. Idea fantasiosa, ma dubbiamente realizzabile in quanto, oltre ai problemi appena citati, nasceva la necessità di tener traccia da qualche parte del file da cancellare. Dunque è stata fatta la seguente scelta: 1. Si imposta un valore di soglia del numero di files che si desiderano all’interno della cartella temporanea 2. Se si è raggiunto il valore di soglia inizia la cancellazione di un numero di file tale che il numero totale rientri nel valore di soglia 3. Se non si è raggiunto il valore di soglia non succede nulla 180 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI Molti si chiederanno il perché di tutto questo, ma è stato inevitabile e soprattutto è molto semplice da spiegare. Alcuni dei file creati non possono essere cancellati perché nonostante tutti gli stream fossero stati chiusi c’è qualcosa da qualche parte che tiene ancora attivo il loro stato e se si cerca di intervenire manualmente alla loro cancellazione viene restituito un messaggio d’errore. Anche con l’ultima soluzione proposta, a lungo, si avranno dei problemi e quando si verificheranno basterà semplicemente cancellare il contenuto delle cartelle temp di cui si è parlato all’inizio del paragrafo. Un progetto concluso, per coloro che lo hanno realizzato è un punto d’arrivo, ma per chiunque lo voglia migliorare non è altro che un punto di partenza: questo aspetto è ciò da cui ricominciare. 181 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI 7.3 Un database Open Source: MySQL Fig. 7.1 – Struttura di memorizzazione dei database. MySQL è un RDBMS veloce e semplice, usato per i database di molti siti Web. La velocità è stato sin dall’inizio l’obiettivo principale degli sviluppatori. Per ottenere maggiore velocità, presero la decisione di offire meno funzionalità rispetto ai maggiori concorrenti (per esempio, Oracle e Sybase). Comunque, anche se MySQL non fornisce funzionalità complete come i suoi concorrenti commerciali, ha tutte le funzionalità necessaria alla maggior parte degli sviluppatori di database. 182 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI È più facile da installare e da usare rispetto ai suoi concorrenti commerciali, e la differenza nel costo favorisce fortemente MySQL. MySQL è sviluppato, distribuito, e supportato da MySQL AB, che è una compagnia Svedese. Questa fornisce due tipi di licenze: • Open source software: MySQL è disponibile con licenza GNU GPL (General Public License) per scopi non commerciali. Chiunque soddisfi le richieste della GPL può usare il software liberamente. Se si usa MySQL per un database in un sito Web, MySQL può essere usato gratuitamente, anche se il sito Web è di tipo commerciale. • Commercial license: MySQL è disponibile con licenza commerciale per quelli che la preferiscono al GPL. Se uno sviluppatore vuole usare MySQL come parte di un nuovo prodotto software e vuole vendere questo prodotto, invece di rilasciarlo sotto licenza GPL, lo sviluppatore deve acquistare una licenza commerciale, ad un costo ragionevole. Trovare il supporto tecnico per MySQL non è un problema. Ci si può iscrivere ad una degli innumerovoli forum di discussione offerti anche sul sito web di MySQL, www.mysql.com. È possibile consultare anche uno degli archivi di e-mail, che contengono una ampia base di conoscenza su MySQL con domande e risposte comuni. Se si vuole un supporto di tipo commerciale, MySQL AB offrer contratti di supporto tecnico — cinque livelli di supporto, dal supporto diretto con e-mail a quello telefonico, a cinque livelli di prezzo. Vantaggi di MySQL MySQL è un database popolare tra gli sviluppatori Web. La sua velocità e leggerezza lo rendono ideale per un sito Web. Aggiungendo a questo il fatto che è open source, il che significa gratis, si ha la spiegazione della sua popularità. Vediamo alcuni dei principali vantaggi: Velocità. Il principale obiettivo delle persone che hanno sviluppato MySQL era la velocità. Conseguentemente, il software, sin dall’inizio, è stato progettato con la velocità in mente. 183 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI Basso costo. MySQL è gratuito sotto la licenza open source GPL, e il costo di una licenza commerciale è ragionevole. Facilità d'uso. È possibile costruire un database MySQL ed interagire con esso usando poche semplici istruzioni nel linguaggio SQL, che è lo standard per la comunicazione con i RDBMS. Supporto sistemi operativi. MySQL gira su una gran numero di sistemi operavi — Windows, Linux, Mac OS, molte varianti di Unix (incluse Solaris, AIX, e DEC Unix), FreeBSD, OS/2, Irix, e altri. Supporto Tecnico. Il supporto tecnico è disponibile. Un gran numero di utenti offre un supporto gratuito attraverso forum di discussione. Gli stessi sviluppatori di MySQL partecipano a questi forum e sono contattabili via email. È possibile ottenere anche il supporto tecnico diretto da MySQL AB ad un prezzo contenuto. Sicurezza. Il sistema flessibile di autorizzazioni di MySQL permette di concedere diversi privilegi sul database (per esempio, il diritto di creare un database o cancellare dati) agli specifici utenti o gruppi di utenti. Le password sono criptate. Supporto grandi databasi. MySQL può gestire fino a 50 milioni di record e più. Il limite predefinito di dimensione per una tabella è 4GB, ma è possibile aumentarlo (se il sistema operativo lo consente) ad un limite teorico di 8 milioni di terabyte (TB). Personalizzabilità. La licenza open source GPL permette ai programmatori di modificare il software di MySQL per adattarlo alle proprie esigenze. Come lavora MySQL Il software di MySQL è composto dal server MySQL, svariati programmi di utilità che aiutano nell'amministrazione dei database MySQL ed alcuni che software di supporto del quale il server MySQL ha bisogno (ma che non è necessario conoscere). Il nucleo del sistema è il server MySQL. 184 CAP. 7 – PROBLEMATICHE E MIGLIORAMENTI Il server MySQL è il gestore del sistema di database. Gestisce tutte le istruzioni riguardanti i database. Per esempio, se si vuole creare un database nuovo, basta inviare un messaggio al server MySQL che dice “crea un nuovo database e chiamalo newdata.” Il server MySQL quindi crea una sottocartella nella sua cartella dati, e la chiama newdata, e vi mette i file necessari nei formati corretti. Allo stesso modo, per aggiungere dati a quel database, basta inviare un messaggio al server MySQL, fornendogli i dati e dicendo dove questi vanno aggiunti. Prima di poter passare le istruzioni al server MySQL , questo deve essere operativo ed in attesa di richieste. Il server MySQL è solitamente impostato in modo da avviarsi all’avvio del computer e rimanere in esecuzione fino al suo spegnimento. Questa è la configurazione comune per un sito Web. Comunque, non è necessario impostare l’avvio in questo modo. Se necessario, è possibile avviarlo manualmente ogni qualvolta sia richiesto accedere ad un database. Quando è in esecuzione, il server MySQL resta in ascolto ed attende che gli arrivino dei messaggi contenenti richieste. Comunicazione con il server MySQL Tutte le interazioni con il database vengono effettuate passando i messaggi al server MySQL. Si possono mandare messaggi al server MySQL in svariati modi, a seconda del linguaggio e della piattaforma utilizzata. Ogni linguaggio ha delle dichiarazioni specifiche che vengono usate per inviare istruzioni al server MySQL. Il server MySQL deve essere in grado di comprendere le istruzioni che gli vengono inviate. Si comunica utilizzando l’SQL (Structured Query Language), che è un linguaggio standard utilizzato dalla maggior parte dei RDBMS. Il server MySQL comprende l’SQL. Dalla parte Java, il driver JDBC non conosce l’SQL, si limita a stabilire la connessione con il server MySQL e invia il messaggio SQL sulla connessione. Il server MySQL interpreta il messaggio SQL ed esegue le istruzioni, a questo punto risponde con un messaggio di ritorno, notificando il suo stato e che cosa ha fatto (o ritornando un errore se non è in grado di capire o eseguire il le istruzioni). Per una descrizione più approfondita della sintassi del linguaggio SQL basta consultare uno dei manuali in materia. 185 CAP. 8 – PUBBLICAZIONE Descrizione degli aspetti fondamentali della pubblicazione di un WebService INDICE ARGOMENTI: 8.1 Il firewall di Linux 8.2 Il comando iptables 186 CAP. 8 – PUBBLICAZIONE 8.1 Il Firewall di Linux Un Firewall linux non è altro che un semplice personal computer normalmente collegato fisicamente (con dei cavi) a più di una rete. Un firewall avrà quindi installata una scheda di rete (interfaccia) per ogni rete cui sarà collegato. Inoltre, dovrà costituire l'unico punto di contatto tra le reti cui è connesso, ovvero dovrà costituire l'unico punto di collegamento tra due o più reti. Un po' come un ponte che collega due o più isole. Senza entrare nei dettagli del protocollo ip, tutte le comunicazioni tra queste reti saranno quindi costrette a passare da questo computer. Questo computer, una volta configurato come firewall, sarà in grado di decidere cosa far passare, cosa scartare o come reagire a determinati eventi. Tornando all'esempio del nostro ponte, configurare il computer come firewall può essere considerato equivalente a mettere una stanga e 2 finanzieri che controllano tutti i veicoli e le persone in transito. Questi 2 finanzieri saranno quindi in grado di agire secondo le istruzioni che gli verranno date dal ministero, bloccando veicoli, arrestando i contrabbandieri o sparando a vista ai ricercati. In linux, la stanga e i finanzieri sono messi a disposizione direttamente dal kernel. Per controllare il kernel, per dare cioè le direttive ai finanzieri, vengono messi a disposizione diversi comandi: con il kernel 2.4, i principali e più avanzati sono comunque il comando ip, tc e iptables, i primi due inclusi nel pacchetto iproute mentre il terzo distribuito indipendentemente. Procedendo con ordine, in linea di principio il comando ip consente di creare nuove isole e nuovi ponti, di gestire quindi le tabelle di routing e le interfacce di rete, il comando iptables di istruire i finanzieri dicendo cosa far passare e cosa non far passare o come reagire a determinate condizioni, consente cioè di creare dei filtri. Infine, il comando tc, consente di stabilire delle priorità e dei limiti sul traffico in ingresso ed in uscita. Ad esempio, un compito che esula dal filtraggio e che quindi riguarda tc potrebbe essere quello di riservare alcune corsie al passaggio di veicoli di emergenza o di servizio, limitando magari il traffico automobilistico, di riservare cioè determinate quantità di banda a determinate tipologie di traffico. 187 CAP. 8 – PUBBLICAZIONE Riassumendo, quindi, si parlerà del comando: • ip per configurare, attivare, disattivare o creare interfacce di rete, nonché per gestire le tabelle di routing (da solo rimpiazza i comandi ifconfig, route e arp). • iptables per bloccare, consentire o registrare il traffico, per effettuare cioè firewalling, ovvero per modificare alcune caratteristiche dei pacchetti in transito, per effettuare cioè NAT (Network Address Translation). • tc per assegnare delle priorità, imporre delle precedenze o dei limiti di banda (tc sta per traffic classifier.), in poche parole, per effettuare dello shaping. Quello che più ci interessa è il comando iptables. 188 CAP. 8 – PUBBLICAZIONE 8.2 Il comando iptables Dovendo parlare di iptables, è indispensabile una piccola introduzione. Il parente più stretto di iptables è sicuramente ipchains il quale aveva introdotto il concetto di catena. iptables ha ripreso il concetto di catena per estenderlo tramite l'introduzione di tabelle. Prima di parlare di tabelle però, ci conviene chiarire il concetto di catena. L'idea di base è abbastanza semplice: un computer collegato in rete con una o più interfacce ha a che vedere con tre tipi di pacchetti: • Pacchetti destinati al firewall stesso • Pacchetti che devono transitare dal firewall ma destinati a qualcun altro • Pacchetti originati dal firewall stesso Di default ipchains ed iptables mettono quindi a disposizioni rispettivamente 3 catene: • La catena di input • La catena di forward • La catena di output In un computer normale (o in un server) verrebbero principalmente utilizzate le catene di input e di output per filtrare il traffico ricevuto e generato dalla macchina presa in considerazione. In un firewall invece, i pacchetti transiterebbero da una scheda di rete all'altra, passando quindi attraverso la catena di forward. Ogni catena è poi costituita da un insieme di regole. Ad ogni regola, è associata un'azione (target). Ogni volta che un pacchetto transita per una catena, tutte le regole vengono controllate in ordine, dalla prima inserita fino all'ultima. Quando una regola risulta applicabile al pacchetto (viene trovato un match) viene applicata al pacchetto l'azione specificata e viene interrotto il processo di ricerca. Se non viene trovata una regola applicabile al pacchetto, la sua sorte (l'azione d'applicare) viene scelta in base alla politica (policy) della catena stessa. In pratica, la policy indica cosa fare di tutti i pacchetti che non rientrano in nessuna regola. 189 CAP. 8 – PUBBLICAZIONE Sia ipchains che iptables poi, consentono di creare o rimuovere catene e di specificare come azione quella di percorrere un'altra catena. Definizione delle policy Iniziamo quindi a parlare di iptables, ed iniziamo proprio definendo la politica di default delle catene di base, cioè l'azione che deve essere presa nel caso in cui nessuna regola si possa applicare al particolare pacchetto. Per fare questo, basta dare: iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP Qui vediamo proprio che se un match non viene trovato, i pacchetti devono essere buttati via (DROP), proprio come se non fossero mai stati ricevuti (o richiesto l'invio, a secondo della catena). Oltre a DROP, esistono molte altre azioni che è possibile specificare, dove le principali sono: • ACCEPT , lascia passare il pacchetto • QUEUE, passa il pacchetto ad un programma in userspace Spesso però capita di usare delle target extensions, ossia dei particolari target che sono forniti tramite dei moduli esterni. E' buona abitudine mettere come politica di default quella di buttare via i pacchetti, dopodichè consentire esplicitamente tutto ciò che vogliamo fare passare. Questo principalmente per due motivi: • è facile rendersi conto di cosa si è dimenticato chiuso (molti degli utenti telefoneranno fino alla saturazione delle linee telefoniche pur di vedere il loro client preferito funzionare), mentre è molto più difficile vedere cosa si è dimenticato aperto. 190 CAP. 8 – PUBBLICAZIONE • non è facile riconoscere tutto ciò che c'è da bloccare. Per esempio, usando una politica di ACCEPT, è estremamente difficile prevedere ciò che potrà essere utilizzato per aggirare le restrizioni, contando che spesso non è obbligatorio seguire gli standard e una persona un po’ sveglia potrebbe modificare il kernel di due macchine linux per utilizzare un protocollo che nulla ha a che vedere col tcp e che mai noi ci saremmo immaginati di dover bloccare (trattandosi, magari, di un protocollo inventato di sana pianta). Un comando che può essere utile nello scrivere le regole si chiama nstreams: questo stamperà a video l'elenco di tutte le connessioni in corso su una rete. Modifiche on the fly - iptables da riga di comando Sebbene sia veramente poco piacevole, è possibile utilizzare iptables direttamente da riga di comando. Nonostante questo, alcune di queste funzioni possono risultare molto utili in fase di testing. Ad esempio, dovendo fare delle misure di banda può essere utile consentire temporaneamente solo il traffico tra determinate macchine, e non è il caso di perdere tempo a modificare file di configurazione o script dalla provata affidabilità. Iniziamo quindi col vedere le regole attive sul kernel, col comando: iptables -nL dove n dice di non risolvere i nomi (passando da indirizzi ip a nomi di domini) e L di listare o elencare (in italiano) tutte le regole. Vediamo alcuni esempi: [root@jtelemed ~]# iptables –nL Chain INPUT (policy DROP) target prot opt source destination ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 reject-with tcp-reset Chain FORWARD (policy DROP) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination 191 CAP. 8 – PUBBLICAZIONE -n viene usato principalmente perché altrimenti ci vorrebbe molto tempo a generare l'output (tentando di connettersi al database). Un problema di iptables -nL (rispetto ad usare un file di configurazione) è che molti dettagli non vengono mostrati e comunque la leggibilità è molto minore. Per avere più dettagli, comunque, è possibile utilizzare l'opzione -v o -vv, con un comando simile a iptables –v -nL [root@jtelemed ~]# iptables –L -v Chain INPUT (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source 1062 124K RH-Firewall-1-INPUT all -- any any anywhere destination anywhere Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source 0 0 RH-Firewall-1-INPUT all -- any any anywhere destination anywhere Chain OUTPUT (policy ACCEPT 1337 packets, 1311K bytes) pkts bytes target prot opt in out source destination Chain RH-Firewall-1-INPUT (2 references) pkts bytes target prot opt in 37 6707 ACCEPT all -- lo 43 2630 ACCEPT icmp -- any any 0 0 ACCEPT ipv6-crypt -- any 0 0 ACCEPT ipv6-auth -- any 0 0 ACCEPT udp -- any dpt:5353 0 0 ACCEPT udp -- any dpt :ipp 880 100 ACCEPT all -- any RELATED, ESTABLISHED 0 0 ACCEPT tcp -- any NEW tcp dpt :http 0 0 ACCEPT tcp -- any NEW tcp dpt :https 3 144 ACCEPT tcp -- any NEW tcp dpt :8085 99 13912 REJECT all -- any with icmp-hosts-proibited out any any source anywhere anywhere destination anywhere anywhere icmp any any any anywhere anywhere anywhere anywhere anywhere 224.0.0.251 udp any anywhere anywhere any anywhere anywhere state any anywhere anywhere state any anywhere anywhere state any anywhere anywhere state any anywhere anywhere reject- udp Se si è interessati ad un'unica catena, si può specificarne il nome dopo il -nL. Con qualcosa di simile a iptables –vv -nL INPUT si vedrà solo la catena di INPUT ed un dump delle informazioni del kernel. Come altre opzioni generiche, si possono utilizzare -x, che mostrerà i valori esatti dei contatori, mentre -Z li azzererà, oppure -t nometabella per visualizzare altre tabelle. 192 BIBLIOGRAFIA Riferimenti telemedicina Molino G., La cartella clinica va on line, Il sole 24 ore Sanità – Management. Dicembre 2002 Nonis M., Braga M., Guzzanti E. Cartella, Clinica e qualità dell’assistenza. Passato, presente e futuro, Il Pensiero Scientifico Editore. Roma 1998. Salvadori P., Informatizzazione e Distretto Socio Sanitario, Panorama della Sanità, anno XV N° 39, ottobre 2002. Hakansson S., Gavelin C., What do we really know about the cost effectiveness of telemedicine?, Journal of Telemedicine and Telcare 2000;6(S1):S133 M.Ciulla, R.Paliotti, F.Magrini, Archivio ecocardiografico multimediale, Cardiologia 1998: 43 n 2: 195-2006 M. Ciulla, R. Paliotti, M.V. Barelli, P.Valentini, F. Magrini Internet: cosa offre la rete informatica al medico, XCVIII Congresso Naz Soc It di Medicina Interna, 1997 Roma 193 BIBLIOGRAFIA Riferimenti tecnologia Feghhi J., Digital Certificates – Applied Internet Security, Addison-Wesley 2000 Jayson Falkner e Kevin Jones, Servlets and JavaServer Pages™: The J2EE™ Technology Web Tier, Addison-Wesley 2003 James Turner, MySQL™ and JSP™ Web Applications: Data-Driven Programming Using Tomcat and MySQL, Sams 2002 James Goodwill, Apache Axis Live, SourceBeat LLC 2004 James R. Groff,Paul N. Weinberg, SQL - The Complete Reference, McGraw-Hill 2003 Elliotte Rusty Harold, Java Network Programming, Second Edition, O’Reilly 2000 Jason Hunter, Java Servlet Programming, Second Edition, O’Reilly 2001 Steve Graham, Simeon Simeonov, Toufic Boubez, Doug Davis, Glen Daniels, Yuichi Nakamura, Ryo Neyama, Building Web Services with Java™: Making Sense of XML, SOAP, WSDL, and UDDI, Sams Publishing 2001 [WSCA10] Heather Kreger, 2001, IBM, Web Services Conceptual Architecture 1.0 194 BIBLIOGRAFIA [SOAP11] W3C, Simple Object Access Protocol (SOAP) 1.1 [WSDL11] W3C, Web Services Description Language (WSDL) 1.1 [UDDI-TWP] Uddi.org, UDDI Technical White Paper Riferimenti web 1. Articoli su http://www.latoserver.it Struttura di una applicazione web - Luca Balzerani 18/04/2002 L'ambiente di Tomcat - Massimo Vassalli 26/02/2002 Installazione di Apache Tomcat - Giuseppe Capodieci 13/03/2001 Java lato server: le Servlet - Giuseppe Capodieci 24/11/2001 2. Articoli su http://www.itportal.it SOAP: l'ultima frontiera per lo scambio dei dati-Francesco Zumpano 02-05-01 3. Ajax e Javascript: http://www.zapatec.com/website/main/products/suite/ http://www.webmasterpoint.org/ajax/home.asp 4. Apache Tomcat, Axis, Soap attachment: http://ws.apache.org/axis/java/apiDocs/org/apache/axis/attachme nts/package-summary.html http://tomcat.apache.org/tomcat-5.5-doc/index.html http://ws.apache.org/axis/java/index.html 195