J2EE 1.4 semplifica lo sviluppo di servizi Web

Al termine della sua presentazione dei servizi Web J2EE (Java 2 Platform, Enterprise Edition) al JavaOne dello scorso anno, l'architetto IBM Jim Knutson ha osservato che "ogni servizio Web ha bisogno di un posto per essere un servizio". Ha quindi suggerito che il posto più ideale per essere un servizio Web fosse all'interno dell'infrastruttura J2EE. Poco più di un anno dopo, il rilascio finale di J2EE 1.4 è imminente e la sua promessa più significativa è di mantenere la visione dei servizi Web J2EE.

Le funzionalità del servizio Web in J2EE 1.4 riguardano sia il lato server che quello client dei servizi Web. Le funzioni estendono J2EE per consentire ai componenti Java aziendali esistenti sul lato server di diventare servizi Web e specificare come un contenitore client J2EE può richiamare i servizi Web. Le tecnologie per entrambi gli scopi esistono da un po 'e le nuove specifiche J2EE si basano su quelle API esistenti per il supporto dei servizi Web. Le nuove specifiche aggiungono alle tecnologie esistenti una serie di requisiti di interoperabilità e un modello di programmazione e distribuzione per l'integrazione dei servizi Web.

Ci sono due specifiche che delineano esplicitamente queste funzionalità aggiunte: Java Specification Request 151, il JSR ombrello per J2EE 1.4 e JSR 109, Web Services per J2EE. Al momento della stesura di questo documento, JSR 109 ha raggiunto la sua fase finale nel JCP (Java Community Process), mentre JSR 151 è nell'ultima fase di votazione. Inoltre, il JCP ha modificato la versione finale di JSR 101, API Java per JAX-RPC (Remote Procedure Call) basata su XML, per supportare i requisiti di interoperabilità J2EE 1.4.

I server delle applicazioni di livello J2EE 1.3 possono anche implementare molte delle funzionalità prescritte da questi JSR. In effetti, molti fornitori di server di applicazioni supportano da tempo varie funzionalità di sviluppo e distribuzione di servizi Web nei loro prodotti esistenti. Le JSR 109 e 151 codificano alcune pratiche esistenti e descrivono nuovi meccanismi con la speranza di creare un modello di integrazione dei servizi Web J2EE universale. I server delle applicazioni di prossima generazione seguiranno probabilmente quel modello unificato e standardizzato.

Dopo un breve sondaggio sulle nuove funzionalità J2EE relative ai servizi Web, questo articolo esamina i nuovi modelli di programmazione client e server, inclusi i nuovi ruoli di distribuzione e gestione dei servizi J2EE associati al supporto dei servizi Web.

Estensioni J2EE relative al servizio Web

Forse le aggiunte più significative e consequenziali a J2EE sono i nuovi requisiti di interoperabilità. I requisiti prescrivono il supporto per SOAP (Simple Object Access Protocol) 1.1 nel livello di presentazione J2EE per facilitare lo scambio di messaggi XML. I contenitori conformi a J2EE 1.4 devono supportare anche il profilo di base WS-I (Web Services Interoperability Consortium). Poiché lo scambio di messaggi XML in J2EE dipende da JAX-RPC, le specifiche JAX-RPC ora richiedono anche il supporto WS-I Basic Profile.

Il risultato è che un'applicazione basata su J2EE 1.4 può essere richiamata come servizio Web, anche da applicazioni non scritte nel linguaggio di programmazione Java. Sebbene questo sia un passo evolutivo per J2EE, poiché la piattaforma ha abbracciato a lungo sistemi non basati su Java, è forse il modo più diretto per facilitare l'interazione con le tecnologie basate su Windows che si basano su .Net.

Il client di un servizio basato su J2EE non deve essere a conoscenza di come viene implementato un servizio. Piuttosto, quel client può utilizzare il servizio basandosi interamente sulla definizione WSDL (Web Services Description Language) del servizio. (Le precedenti colonne dei servizi Web JavaWorld spiegano come scoprire i servizi in base alle loro definizioni WSDL e come creare e utilizzare le definizioni WSDL. Vedere Risorse per i collegamenti.) Sebbene le specifiche J2EE non spieghino i meccanismi esatti di tale interazione, J2EE 1.4 " L'adozione del WS-I Basic Profile, che anche Microsoft afferma di seguire, probabilmente renderà comune l'interazione J2EE-.Net.

Per facilitare l'accesso alle definizioni WSDL, J2EE 1.4 aggiunge il supporto per lo standard JAXR (Java API for XML Registries). Le librerie JAXR sono ora una parte richiesta del client dell'applicazione J2EE, EJB (Enterprise JavaBeans) e dei contenitori Web (non il contenitore dell'applet, però). Poiché WS-I Basic Profile richiede il supporto per UDDI (Universal Description, Discovery e Integration) 2.0, i client J2EE, nonché i componenti EJB e i servlet, possono interagire con i registri dei servizi Web pubblici. ("I servizi Web prendono il volo con JAXR" ( JavaWorld, maggio 2002) offre un tutorial su JAXR.) La Figura 1 illustra le librerie aggiuntive relative ai servizi Web supportate da J2EE 1.4.

Infatti, J2EE ritiene che un servizio Web sia un'implementazione di una o più interfacce definite da un documento WSDL. Le operazioni descritte in WSDL vengono prima associate ai metodi Java seguendo le regole di associazione WSDL-Java della specifica JAX-RPC. Una volta definita un'interfaccia Java corrispondente a un file WSDL, è possibile implementare i metodi di tale interfaccia in uno dei due modi: come un bean di sessione senza stato in esecuzione nel contenitore EJB o come classe Java in esecuzione nel contenitore servlet J2EE. Infine, fai in modo che il rispettivo contenitore ascolti le richieste SOAP in arrivo e associ tali richieste alla rispettiva implementazione (EJB o servlet). Per elaborare le chiamate SOAP in entrata, J2EE 1.4 richiede il runtime JAX-RPC come servizio contenitore J2EE aggiuntivo.

In linea con l'architettura J2EE, il contenitore di un'implementazione del servizio media l'accesso a un servizio Web: se esponi un componente EJB o un servlet come servizio Web J2EE, i client del tuo servizio possono richiamare quel servizio solo indirettamente, tramite il contenitore. Ciò consente all'implementazione di un servizio di trarre vantaggio dalla sicurezza del contenitore, dalla gestione dei thread e persino dalle garanzie di qualità del servizio. Inoltre, i contenitori consentono di prendere importanti decisioni sul servizio Web, come i vincoli di sicurezza, al momento della distribuzione. Infine, il modello basato su container di J2EE rende portabile la distribuzione del servizio Web: è possibile sviluppare un servizio Web basato su Java utilizzando qualsiasi strumento J2EE e aspettarsi che il servizio venga eseguito in qualsiasi altra implementazione di container conforme.

Un client di servizi Web, d'altra parte, rimane inconsapevole della presenza di un contenitore di servizi Web. Il client vede invece una porta che rappresenta un'istanza di endpoint di rete di un servizio Web. Tale endpoint segue il modello SEI ( Service Endpoint Interface ) JAX-RPC e fornisce un'implementazione dell'interfaccia del servizio. Un client visualizza ogni servizio Web J2EE come una combinazione SEI e porta. Un singolo contenitore J2EE può ospitare molte di queste combinazioni, come illustrato nella Figura 2. Ogni combinazione SEI / porta è un'istanza di un servizio Web.

Notare che il client in questa architettura può essere un client J2EE, in esecuzione all'interno del contenitore del client J2EE, o un client non J2EE. Qualsiasi client compatibile con WS-I Basic Profile può utilizzare un servizio Web J2EE, ma ogni client può seguire diversi modelli di programmazione. La specifica dei servizi Web J2EE delinea un modello di programmazione per i client che vengono eseguiti all'interno del contenitore del client dell'applicazione J2EE e un altro modello, il modello di programmazione del server, per le implementazioni del servizio Web che vengono eseguite nell'EJB o nei contenitori servlet.

Il modello di programmazione client del servizio Web J2EE

L'essenza del modello di programmazione client del servizio Web è semplificare l'uso delle API definite in JSR 67 (API Java per XML Messaging, JAXM), 93 (JAXR) e 101 (JAX-RPC) e fornire un framework completo per utilizzando queste API insieme nel contenitore client J2EE.

In linea con il modello di programmazione client J2EE, un client di servizi Web è remotabile e fornisce trasparenza locale / remota. Il provider della porta del servizio Web e il contenitore in cui viene eseguita la porta definiscono il modo in cui un client vede un servizio Web. Il client accede sempre alla porta e non viene mai passato un riferimento diretto all'implementazione di un servizio Web. Un client del servizio Web J2EE rimane ignaro di come opera una porta e deve occuparsi solo dei metodi definiti da una porta. Questi metodi costituiscono l'interfaccia pubblica di un servizio Web. Inoltre, un client deve considerare l'accesso a una porta del servizio Web come senza stato tra le chiamate di servizio. Per quanto riguarda il client, una porta non ha un'identità univoca: un client non ha modo di determinare se comunica con porte identiche attraverso le chiamate di servizio.

Il client ottiene l'accesso a una porta in base all'interfaccia di servizio della porta. I servizi Web J2EE si basano su JAX-RPC per definire la relazione tra una porta e la sua interfaccia di servizio. JAX-RPC crea quella relazione in base alle regole di elaborazione WSDL. Pertanto, la definizione WSDL del servizio Web governa in ultima analisi il comportamento della porta. In base alla definizione JAX-RPC, l'interfaccia del servizio può essere un'interfaccia generica che implementa direttamente l' javax.xml.rpc.Serviceinterfaccia o un "servizio generato", che è un sottotipo di tale interfaccia. Quest'ultimo tipo di interfaccia è specifico del tipo di servizio Web.

Nel modello di programmazione J2EE, il client ottiene un riferimento a un Serviceoggetto del servizio Web tramite un'operazione di ricerca JNDI (Java Naming and Directory Interface). La ricerca JNDI avviene tramite un nome logico o un riferimento al servizio per il servizio Web. Come con tutte le risorse basate su directory, un client deve dichiarare di quali risorse ha bisogno nel suo descrittore di distribuzione (ne parleremo più avanti).

La specifica dei servizi Web Java (JSR 109) consiglia che tutti i servizi Web siano inclusi nel servicesottocontesto JNDI . Il contenitore client collega l'interfaccia del servizio descritta da quel riferimento nel java:comp/envcontesto dei nomi dell'ambiente client. Dichiarando un riferimento al servizio nel descrittore di distribuzione del client, il contenitore del client garantisce che il servizio a cui si fa riferimento sia disponibile nelle risorse compatibili con JNDI. Il seguente frammento di codice mostra come ottenere un riferimento a un servizio Web basato su J2EE tramite la ricerca JNDI:

InitialContext ctx = new InitialContext (); Service myService = (Service) ctx.lookup ("java: comp / env / services / MyWebService");

Il codice precedente ottiene un oggetto servizio generico: un oggetto senza un tipo specifico. Si accede a un servizio generato da JAX-RPC allo stesso modo, questa volta trasmettendo il servizio al tipo di interfaccia del servizio Web specifico:

InitialContext ctx = new InitialContext (); MyWebService myService = (MyWebService) ctx.lookup ("java: / comp / env / services / MyWebService");

Si noti che questo codice presuppone che il MyWebServiceriferimento si associ a un oggetto che implementa l' MyWebServiceinterfaccia. Poiché l'associazione del servizio è facilitata al momento della distribuzione di un servizio Web, gli strumenti J2EE dovrebbero garantire tale coerenza. Tutti i server delle applicazioni conformi a J2EE 1.4 devono supportare la ricerca del servizio basata su JNDI.

Una volta che un client ottiene l' Serviceoggetto di un servizio Web , può utilizzare quell'oggetto per recuperare javax.xml.rpc.Callun'istanza che esegue l'effettiva chiamata del servizio. Il client ha tre opzioni per ottenere una Call: tramite uno stub, un proxy di servizio dinamico o un DII (Dynamic Invocation Interface). Non discuterò in questo articolo le differenze tra questi metodi poiché, indipendentemente da come Callviene creato, si Callriferisce direttamente alla porta del servizio, l'unico oggetto di cui il client deve essere consapevole quando richiama il servizio Web. Tutti i contenitori conformi a J2EE 1.4 devono supportare i Servicemetodi di interfaccia e quindi consentire a un client di ottenere un riferimento a un Calloggetto per un servizio Web e alla porta di quel servizio, tramite Call.

Notare che, a differenza dell'utilizzo di JAX-RPC al di fuori di J2EE, un client non dovrebbe utilizzare la ServiceFactoryclasse JAX-RPC per ottenere un nuovo servizio. Invece, il client dovrebbe ottenere l'accesso a Serviceda un'origine basata su JNDI, poiché il riferimento a un servizio recuperato da JNDI avrà tutte le impostazioni e le configurazioni necessarie per richiamare la particolare istanza del servizio. Dal punto di vista di un client, tale differenza è in qualche modo analoga a come un client J2EE richiama un JDBC DataSourcetramite l'interfaccia JNDI per accedere a un database, invece di configurare manualmente Connectionun'istanza JDBC .

Con Callquell'oggetto in posizione, il client segue la semantica JAX-RPC della chiamata di procedura remota. Ad esempio, il client potrebbe utilizzare il invoke()metodo su quello Callper interagire con il servizio Web. (Per un esempio di richiamo del servizio in stile JAX-RPC, vedere "Mi piace il tuo tipo: descrivere e richiamare i servizi Web in base al tipo di servizio" ( JavaWorld, settembre 2002).)

Il modello di programmazione del server del servizio Web

Un servizio Web basato su J2EE può seguire una delle due possibili implementazioni: Se il servizio è implementato come una normale classe Java, deve essere conforme ai requisiti del contenitore servlet JAX-RPC. Oppure, se il servizio è definito per essere eseguito nel contenitore EJB, deve seguire il modello di programmazione richiesto per i bean di sessione EJB senza stato. Indipendentemente dal metodo di implementazione, ogni contenitore fornisce all'implementazione del servizio Web supporto per il ciclo di vita, gestione della concorrenza e un'infrastruttura di sicurezza.

La responsabilità principale del contenitore del server J2EE è associare e inviare richieste SOAP, nel caso EJB, a bean di sessione senza stato e, nel caso del contenitore servlet, a metodi nelle classi di endpoint del servizio JAX-RPC. Mentre la specifica JAX-RPC definisce un modello di programmazione per quest'ultima opzione, il J2EE Web services JSR (JSR 109) delinea un modello analogo per i bean di sessione EJB senza stato.