How to develop the Handlers in JAX-WS
Cos'è JAX-WS
JAX-WS è l'acronimo di Java API for XML Web Services, una tecnologia dedicata esclusivamente allo sviluppo di Web Service in Java che comunicano utilizzando messaggi SOAP/XML. Come il resto delle API della piattaforma Java EE, anche JAX-WS utilizza le annotazioni (introdotte a partire da Java SE 5) utili per la semplificazione dello sviluppo sia dei Producer sia dei Consumer.
L'implementazione di riferimento (JAX-WS for Reference Implementation) è un progetto open source e fa parte dello stack GlassFish => Metro.
Uno degli aspetti di JAX-WS che ritengo importante per avermi salvato in alcune situazioni, e che vorrei introdurre in questo articolo, è rappresentato dai cosiddetti Handlers. Restando nell'ambito della programmazione event-driven, gli handler, sono dei gestori di eventi, chiamati quindi per gestire e rispondere ad un determinato evento.
Cosa sono gli handler e per cosa utilizzarli
Gli handler JAX-WS (che da ora in poi chiameremo gestori) sono dei Message Interceptors che possono essere collegati all'ambiente di esecuzione JAX-WS per fare ulteriori elaborazioni dei messaggi in entrata e in uscita, inoltre sono totalmente indipendenti dal codice applicativo (a livello dell'applicazione) e sono in grado di fornire funzionalità di basso livello che agiscono direttamente sui messaggi. La specifica JAX-WS definisce di base due tipi di gestore:
- Gestori di Protocollo (Protocol Handlers): operano sulle proprietà del contesto del messaggio e sono specifici di un protocollo, sono nelle condizioni di poter accedere o modificare degli aspetti specifici del protocollo di un messaggio. Dato che sono limitati a configurazioni specifiche di SOAP, sono in genere chiamati come "gli handler SOAP";
- Gestori di Logica (Logical Handlers): sono in grado di elaborare il Payload del messaggio e le proprietà di memorizzazione nel contesto del messaggio e non possono in alcun modo intervenire su parti specifiche di protocollo, come per esempio gli header.
- modifica dei dati contenuti nel contesto del messaggio;
- modifica della richiesta, della risposta o del fault;
- tracciamento di richieste e risposte;
- problematiche legate alla sicurezza.
Il diagramma di Figura 1 mostra i punti d'intervento dei gestori per un messaggio SOAP. I gestori sono richiamati con un Message Context che fornisce i metodi per accedere e modificare i messaggi in entrata e in uscita e di gestire un insieme di proprietà.
I gestori di protocollo (che allo stato attuale delle specifiche prevedono solo SOAP), devono estendere l'interfaccia javax.xml.ws.handler.soap.SOAPHandler e sono richiamati con un SOAPMessageContext. I gestori di logica devono invece estendere l'interfaccia javax.xml.ws.handler.LogicalHandler e sono richiamati con un LogicalMessageContext.
In Figura 2 è mostrato il Class Diagram degli handler JAX-WS con evidenza di entrambe i tipi di gestore: di logica e di protocollo. Ho preferito inserire nel diagramma anche due classi che realizzano, una il gestore di protocollo (che ho chiamato SOAPLogginHandler) e una il gestore di logica (che ho chiamato LogicalLogginHandler), entrambe devono implementare i seguenti metodi:
- handleMessage(): Questo è richiamato per i messaggi in entrata (inbound) e in uscita (outbound);
- handleFault(): Questo è richiamato quando il messaggio contiene un errore di protocollo;
- close(): Questo metodo è richiamato dopo il completamento dell'elaborazione dei messaggi da parte di tutti i gestori per ogni chiamata al servizio (dopo il completamento del MEP - Message Exchange Pattern). Questo può risultare utile per "pulire" eventuali risorse utilizzate durante l'elaborazione del messaggio.
I gestori di protocollo possono coesistere con i gestori logici all'interno della cosiddetta handler chain. Durante la fase di esecuzione la handler chain è riordinata sulla base del "verso" che il flusso del messaggio segue: outbound o inbound.
Nel caso di un message outbound i gestori di logica sono eseguiti prima dei gestori di protocollo, viceversa, nel caso di un message inbound i gestori di protocollo sono eseguiti prima dei gestori di logica. La Figura 3 mostra come i gestori di protocollo e i gestori di logica sono richiamati durante un processo d'invocazione Request-Response di un servizio web.
Una delle mie ultime esperienze che è stata poi il trigger per la pubblicazione di questo articolo, mi ha portato ad utilizzare il meccanismo degli handler (in qualità di consumer di un servizio) per applicare un workaround a causa di un default namespace (vuoto, ma comunque previsto dallo standard) sul messaggio di richiesta che dava fastidio al server in fase valutazione di un'espressione XPath. Dato che lato server era problematico modificare il servizio affinchè XPath supportasse i default namespace, a questo punto ho creato un gestore logico (LogicalHandler) che sul messaggio di richiesta rimuove i default namespace.
Conclusioni
In questo breve sunto abbiamo visto che gli Handler di JAX-WS sono dei componenti di semplice implementazione (tramite una classe Java che estende una interfaccia nota) e molto utili in tutti quegli scenari d'integrazione, monitoring, correzione e compensazione di eventuali errori oltre che alla gestione della sicurezza.
Riferimenti
[1] JAX-WS Reference Implementation (RI) Project
[2] Getting Started with JAX-WS Web Services
[3] Developing JAX-WS Web Service Clients
[4] JSR 181: Web Services Metadata for the JavaTM Platform
[5] JAX-WS Tutorial