Quando qualche articolo fa abbiamo parlato di annotations, abbiamo discusso di come l'adozione di questo nuovo strumento potesse semplificare la vita degli sviluppatori. La particolarità di definire già a livello di scrittura del codice delle configurazioni rende questo strumento particolarmente utile per chi fa uso di framework o aderisce a specifici modelli di sviluppo.
Un esempio lo abbiamo visto con gli EJB 3.0, dove attraverso l'annotazione degli elementi siamo riusciti a sviluppare enterprise java bean in maniera molto più veloce rispetto al precedente modello di sviluppo. Oggi vedremo come sviluppare web service attraverso l'uso di annotations. Con due esempi pratici vedremo come sia possibile sviluppare il servizio mettendo da parte qualsiasi tipo di configurazioni XML.
Semplificare lo sviluppo di web service con delle procedure standard è stato un lavoro di standardizzazione che ha portato alla nascita della JSR 181 (Java Specification Request). Questa specifica definisce il modello di configurazione e le annotazioni che potranno essere utilizzate per sviluppare il web service utilizzando le annotations di cui andremo a parlare. È importante dire che lo sviluppo, e il successivo deploy, del web service dovrà essere fatto su un application server compatibile con questa specifica (JBoss 5, Glassfish o SUN Application server, WebLogic, ecc lo sono).
Fino a qualche tempo fa produrre tutto il codice per far funzionare un web service era un'operazione piuttosto lunga e noiosa. Se ci pensate bene, i web service non aggiungono nulla di particolare a quanto già normalmente fanno le applicazioni. Quello che fanno è rendere l'accesso al servizio obliquo, disponibile a qualsiasi piattaforma di sviluppo o altro applicativo in maniera standard. Il lavoro principale, quindi, è sempre stato quello di gestire delle complesse configurazioni che permettessero ai tool di costruire i documenti WSDL e i messaggi SOAP.
Tool di sviluppo come Axis, e altre facility messe a disposizione dagli application server, hanno aiutato in questi ultimi anni lo sviluppo, e dunque la diffusione, a beneficio dell'architettura SOA che è diventata di fondamentale importanza nel mondo dei servizi IT.
Questo è uno dei motivi per cui la specifica è stata pensata: rendere indipendente dall'application server la produzione del servizio (e quindi il successivo deploy).
Gli esempi che andremo a vedere sono stati sviluppati utilizzando l'ambiente di sviluppo NetBeans integrato con l'application server Sun Application Server 9. Per la teoria dei web service vi rimando alla guida apposita.
Partiamo con un esempio semplice, un classico Echo Service, per mostrarvi quanto sia davvero facile implementare un web service attraverso le annotations.
Listato 1. Echo Service
//WebLayerWebService.java
package it.html.layer.web;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
// La classe POJO viene utilizzata per racchiudere la logica di
// business che risponde al metodo del web service
@WebService()
public class WebLayerWebService {
//Il metodo prende un parametro e ne restituisce un eco in maiuscolo
@WebMethod
public String echo(@WebParam(name = "sentence") String sentence) {
/*
* Qui dovrebbe esserci tutta la logica Java, connessioni al layer
* di persistenza, utilizzo del layer JEE, ... senza preoccuparsi dello
* stack del web service, cioè come verrà convertita la richiesta in messaggi
* SOAP.
*/
return "ECHO: "+sentence.toUpperCase();
}
}
Creiamo una classe POJO che annotiamo con l'annotation @WebService
, indicando così che la logica di quella classe dovrà essere deployata e configurata per rispondere come web service.
A questo punto aggiungiamo i metodi che vogliamo esporre. Creiamo il metodo echo
e lo annotiamo come @WebMethod
, specificando che quel metodo (e relativi tipi di ritorno e parametri) saranno esposti per rispondere alle richieste. In questo caso il metodo è un semplice echo della richiesta.
Ovviamente importiamo tutto il necessario per poter compilare ed effettuiamo l'operazione di packaging. Il layer di questa classe è quello web (nel secondo esempio vedremo un web service enterprise), per cui creeremo un archivio war (web archive).
Nel nostro semplice esempio abbiamo usato un'annotazione vuota, lasciando spazio alla configurazione di default dei parametri del WSDL. Volendo modificarli utilizzeremo questa notazione:
@WebService ( name = "echoWebService",
serviceName=" echoWebService ",
targetNamespace = "http://html.it/webservices")
Vi ricordiamo che vi sono altre annotazioni che potrete utilizzare a livello di classe come per esempio @SOAPBinding
, per definire come codificare i messaggi SOAP, a noi non interessa ridefinirli per ora.
Quando effettuiamo il deploy (su un application server che supporta la specifica JSR 181) avviene la configurazione del servizio e la creazione della struttura del web service, generalmente una servlet che fa da wrapper per la classe, occupandosi della gestione dei messaggi SOAP e dell'esposizione del WSDL (tutto dipende dall'engine utilizzato). Se utilizzate Sun Application Server, avrete automaticamente una pagina di test del servizio che potete utilizzare come prova; questo il risultato:
Figure 1. Test echo service
Inserendo il testo, avremo una pagina che mostrerà il risultato e i relativi messaggi SOAP scambiati (request, con la richiesta e response, con la risposta):
Figure 2. Risultato esecuzione echo service
Come avrete modo di testare, la procedura di sviluppo diventa davvero semplice e indolore, senza alcuna preoccupazione per quanto riguarda la configurazione.
Secondo esempio
Abbiamo sviluppato un web service che agisce a livello di web application, quindi una semplice classe java che risponde al servizio. Cosa dovremo fare nel caso vogliamo utilizzare le potenzialità del livello enterprise? La risposta è semplice, annotare la classe come Web Service e anche come EJB.
Nella guida J2EE abbiamo visto che creare un web service da un endpoint EJB ha notevoli vantaggi in quanto ci consente di sfruttare tutte le potenzialità (scalabilità, affidabilità, performance, ecc) della piattaforma enterprise. Per rendere più interessante questo esempio utilizzeremo un progetto già visto negli scorsi articoli e vi costruiremo su un wrapper web service che ne esponga alcuni metodi.
Riprendiamo il progetto sulla Tag Cloud e sviluppiamo quindi un web service (enterprise layer) esponendo i metodi per l'aggiunta di un tag (addTag
) e per verificarne l'esistenza (esisteTag
):
Listato 2. Estende la Tag Cloud
//EnterpriseLayerWebService.java
package it.html.ws.enterpriselayer;
..//
//Associamo il web service a uno stateless session bean creato in stile 3.0 attraverso le annotazioni
@Stateless()
@WebService()
public class EnterpriseLayerWebService {
//Il layer di persistenza che utilizzeremo
DBManager database;
@PostConstruct
public void postConstruct(){
try {
database=new DBManagerConcrete();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
//Il metodo verifica se il tag esiste o meno
@WebMethod
public boolean esisteTag(@WebParam(name = "tag") String tag) {
//All'interno del metodo gestiamo tutta la logica di business necessaria a portare a termine la funzione
Tag t=database.loadTag(tag);
if(t==null){
return false;
return true;
}
//Il metodo aggiunge il tag alla lista
@WebMethod
public void addTag(@WebParam(name = "tag") String tag) {
//Creiamo un nuovo tag e lo salviamo utilizzando i metodi del layer di persistenza
Tag t=new Tag(tag);
database.add(t);
}
}
}
Rispetto all'esempio precedente annotiamo la classe come @Stateless
, oltre che come @WebService
, proprio per specificare che si tratta di uno stateless EJB. La classe avrà un riferimento al layer di persistenza per gestire le operazioni di logica ed espone i due metodi, annotati entrambi come @WebMethod
.
È evidente che all'interno del metodo potrà essere gestita la logica di business in dipendenza delle esigenze applicative. In questo esempio abbiamo riproposto quanto già avevamo scritto. In altri casi avrete modo di accedere ad altri bean (per esempio bean di entità) o in generale creare delle logiche più o meno complesse.
Utilizzando il pannello di test creato dal nostro application server, vediamo qualche prova che abbiamo fatto:
Figure 3. Test del metodo esisteTag
Figure 4. Test del metodo addTag e query sul database