Realizzare un Web service
In questo capitolo vedremo come sia possibile esporre un Web Service Soap attraverso EJB 3. I Web Services rappresentano la piattaforma
standard per l'interoperabilità tra diversi sistemi sulla rete. Un Web Service è definito attraverso un file WSDL (Web
Service Description Language) che contiene la descrizione del servizio, in particolare l'interfaccia con i metodi esposti.
Con EJB 3 abbiamo due approcci per realizzare un servizio web: Bottom Up e Top Down. Con Bottom Up realizziamo
la classe EJB con le annotations e generiamo il file WSDL con cui
un client può generare le classi proxy per l'invocazione del servizio. L'approccio Top Down prevede invece il percorso inverso: editiamo
il file WSDL dal quale successivamente generiamo l'EJB che lo implementa (vedi Guida Web Services).
Consideriamo nuovamente il session bean convertitore di temperatura e vediamo in che modo esporre la sua interfaccia
come Web Service JAX-WS (Java Api Xml Based for Web Services). JAX-WS è un tipologia di programmazione che semplifica lo
sviluppo delle applicazioni orientate ai servizi attraverso il supporto di un modello standard, annotation-based, per sviluppare Web Service e relativi client.
Continuiamo la nostra progettazione specificando il contratto delle funzionalità esposte tramite interfacce
Java. Per il convertitore di temperatura abbiamo già definito l'interfaccia/contratto Converter:
package it.html.progetto1.ejb30;
public interface Converter {
float celsiusToFahrenheit(float temperature);
float fahrenheitToCelsius(float temperature);
}
Abbiamo quindi successivamente introdotto le interfacce local e remote attraverso la sua estensione:
package it.html.progetto1.ejb30;
import javax.ejb.Remote;
@Remote
public interface ConverterBeanRemote extends Converter{}
package it.html.progetto1.ejb30;
import javax.ejb.Local;
@Local
public interface ConverterBeanLocal extends Converter{}
Il session bean stateless, implementando entrambe le interfacce, fornisce un accesso a client locali e remoti.
Definiamo ora un'interfaccia che espone le funzionalità di conversione della temperatura attraverso
Web Service. Proseguiamo quindi con l'estensione di Converter
ma ridefinendo i suoi metodi attraverso particolari annotations:
package it.html.progetto1.ejb30;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import it.html.progetto1.ejb30.Converter;
@WebService
@SOAPBinding(style=SOAPBinding.Style.RPC)
public interface ConverterBeanWS extends Converter {
@WebMethod(operationName="celsiusToFahrenheit", action="http://localhost:8080/CelsiusToFahrenheit")
@WebResult(name="celsiusValue")
float celsiusToFahrenheit(@WebParam(name="temperature", mode=WebParam.Mode.IN) float temperature);
@WebMethod(operationName="fahrenheitToCelsius", action="http://localhost:8080/FahrenheitToCelsius")
@WebResult(name="fahrenheitValue")
float fahrenheitToCelsius(@WebParam(name="temperature", mode=WebParam.Mode.IN) float temperature);
}
L'annotation @WebService
permette di marcare ConverterBeanWS
come interfaccia endpoint di un Web Service. @SOAPBinding
consente di specificare gli stili per il formato XML contenuto nel body di un messaggio SOAP: RPC e DOCUMENT. Nel nostro caso scegliamo lo
stile RPC (Remote Procedure Call) in quanto si adatta al tipo di Web Service che stiamo realizzando. Il body di un messaggio SOAP in stile
RPC è costruito con l'assunzione che il client che lo invoca desideri farlo nello stesso modo in cui invocherebbe un normale metodo o funzione
parte della sua applicazione.
Il body SOAP contiene quindi un tag con il nome del metodo da invocare e diversi tag figli
per ciascun parametro definito dal metodo. Con lo stile DOCUMENT (default) non si presentano restrizioni su come l'XML del body di un messaggio SOAP
deve essere costruito, abbiamo completa libertà sulla sua struttura potendo inoltre fornire uno SCHEMA XSD per la validazione.
Utilizzando l'annotation @WebMethod
possiamo specificare quali metodi faranno parte dell'interfaccia offerta dal servizio, Inoltre @WebMethod
,
@WebParam
e @WebResult
consentono di personalizzare le parti del documento WSDL associato al servizio, assegnando alias a metodi, parametri di input ed output.
Concludiamo l'esposizione
del session bean come Web Service agendo sulla classe del bean it.html.progetto1.ejb30.ConverterBean
. Facciamo in modo
che implementi anche l'interfaccia ConverterBeanWS
ed aggiungiamo l'annotation @WebService
:
package it.html.progetto1.ejb30;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.interceptor.Interceptors;
import javax.jws.WebParam;
import javax.jws.WebService;
import it.html.progetto1.interceptor.ejb30.InterceptorLoggerBean;
/**
* Session Bean and Web Service implementation class ConverterBean
*/
@Stateless(name="ConverterBean", mappedName = "ConverterBean")
@WebService(
targetNamespace="urn:ConverterBeanService",
portName="ConverterBeanPort",
serviceName="ConverterBeanService",
endpointInterface="it.html.progetto1.ejb30.ConverterBeanWS")
@Interceptors(InterceptorLoggerBean.class)
public class ConverterBean implements ConverterBeanRemote, ConverterBeanLocal, ConverterBeanWS {
public ConverterBean() {}
@Override
@TransactionAttribute(TransactionAttributeType.NEVER)
public float celsiusToFahrenheit( @WebParam(name="temperature", mode=WebParam.Mode.IN) float temperature ) {
return temperature * 1.8f + 32;
}
@Override
@TransactionAttribute(TransactionAttributeType.NEVER)
public float fahrenheitToCelsius( @WebParam(name="temperature", mode=WebParam.Mode.IN) float temperature ) {
return (temperature - 32) / 1.8f;
}
}
Dal punto di vista dell'implementazione abbiamo terminato il nostro Web Service e possiamo procedere con il deploy.