Webservices
Transcription
Webservices
1 5. Web-Services • Kommunikation zwischen Client und Server über XML-Format SOAP Client • Beschreibung von Webservices in WSDL (Web Services Description Language) Web Service Protokollstapel Entdeckung • Suche passender Dienste mit UDDI (Universal Description, Discovery, and Integration) • Potential: führende Integrationsinfrastruktur (“kleinster gemeinsamer Nenner”) SOAP Server UDDI Beschreibung WSDL Verpackung SOAP Übertragung HTTP, SMTP, FTP 2 5.1 SOAP • XML-Format zur Übermittlung von Web-Service-Aufrufen und deren Antworten SOAP−Envelope SOAP−Header Header−Block Header−Block SOAP−Body Nachrichten−Body 3 Details zu SOAP • bei Fehler: spezielle fault-Antwort (= ˆ Exception) • durch Header: u.a. optionale Zugangskontrolle, Transaktionsverwaltung • Web-Services sind typischerweise zustandslos • daher ggf. Zustand (z.B. Session-Id) als Parameter • unübersichtliche XML-Struktur wird in Client- und Server-Code durch Proxy-Klassen bzw. Webserver versteckt • Implementierungen: z.B. Apache Axis (→ Tomcat), JAX-WS 4 Beispiel: SOAP-Anfrage <?xml version=’1.0’ encoding=’UTF-8’?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2001/09/soap-envelope/" xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <ns1:getWeather xmlns:ns1="urn:examples:weatherservice" SOAP-ENV:encodingStyle="http://www.w3.org/2001/09/soap-encoding/"> <zipcode xsi:type="xsd:string">48149</zipcode> </ns1:getWeather> </SOAP-ENV:Body> </SOAP-ENV:Envelope> (angelehnt an: E. Cerami: Web Services, O’Reilly, 2002) 5 Beispiel: SOAP-Antwort <?xml version=’1.0’ encoding=’UTF-8’?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2001/09/soap-envelope/" xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <ns1:getWeatherResponse xmlns:ns1="urn:examples:weatherservice" SOAP-ENV:encodingStyle="http://www.w3.org/2001/09/soap-encoding/"> <return xsi:type="xsd:int">23</return> </ns1:getWeatherResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 6 SOAP-Nachrichtenformate • document: SOAP-Body ist beliebiges XML-Dokument (default) • rpc: SOAP-Body enthält Methodenname und Parameter • literal: Daten gemäß XML-Schema (XSD) strukturiert (default) • encoded: verwendet vordefinierte XML-Tags für übliche Basistypen (z.B. int, double) sowie Arrays und Structs • typische Kombinationen: document/literal (empfohlen) und rpc/encoded • kein verteiltes Objektmodell (anders als z.B. CORBA) 7 5.2 WSDL • Format zur Beschreibung von Web-Services <definitions> <types> Datentypen <messages> Nachrichten <porttype> Operationen <binding> Übertragungsprotokolle <service> Zugriffsadresse 8 Beispiel: WSDL-Beschreibung des Wetter-Web-Service <?xml version="1.0" encoding="UTF-8"?> <definitions name="WeatherService" targetNamespace="http://www.ecerami.com/wsdl/WeatherService.wsdl" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.ecerami.com/wsdl/WeatherService.wsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <message name="getWeatherRequest"> <part name="zipcode" type="xsd:string"/> </message> <message name="getWeatherResponse"> <part name="temperature" type="xsd:int"/> </message> <portType name="Weather PortType"> <operation name="getWeather"> <input message="tns:getWeatherRequest"/> <output message="tns:getWeatherResponse"/> </operation> </portType> 9 <binding name="Weather Binding" type="tns:Weather PortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="getWeather"> <soap:operation soapAction=""/> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:weatherservice" use="encoded"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:weatherservice" use="encoded"/> </output> </operation> </binding> <service name="Weather Service"> <documentation>WSDL File for Weather Service</documentation> <port binding="tns:Weather Binding" name="Weather Port"> <soap:address location="http://localhost:8080/soap/servlet/rpcrouter"/> </port> </service> </definitions> 10 5.3 Web-Services mit .NET • Web-Service-Klasse erbt von System.Web.Services.WebService • bietet ggf. Properties Session, Application, Context, User (→ Zustand) • Verweis auf Hintergrundcode in .asmx-Datei <%@ WebService Language="C#" CodeBehind="MeinService.asmx.cs" Class="..." %> • deployed in MS Internet Information Server (IIS) • Annotationen [WebService], [WebMethod], . . . • (z.B.) Visual Studio erzeugt Client-Proxy-Klasse aus WSDL-Beschreibung • Web-Service-Namen können nicht überladen werden • fault-Antwort wird von Proxy in SoapException umgewandelt 11 Beispiel: Addier-Web-Service mit .NET using System.Web.Services; using System.Web.Services.Protocols; ... namespace AddierService { /// <summary>Dieser Webservice addiert zwei Zahlen.</summary> [WebService(Namespace = "http://localhost/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1 1)] public class Addierer : System.Web.Services.WebService { [WebMethod(Description="Dieser Webservice addiert 2 Zahlen.")] public int Addiere(int[] a) { int summe = 0; foreach(int x in a) summe += x; return summe;} } } 12 Beispiel: Web-Service-Client mit .NET using AddierService; ... namespace AddierClientNSp { public partial class AddierClient : System.Web.UI.Page { public void Addiere(object sender, EventArgs ev) { int[] val = new int[2]; val[0] = Convert.ToInt32(x.Text); val[1] = Convert.ToInt32(y.Text); // Projektname.Webverweisname.Service-Klasse Addierservice.AddierWebService.Addierer service = new Addierservice.AddierWebService.Addierer(); result.Text = "Ergebnis von .NET: " + service.Addiere(val); Addierservice.AddierServiceEJB.AddiererIFService service2 = new Addierservice.AddierServiceEJB.AddiererIFService(); try { result.Text += ", Ergebnis von Java-Web-Service: " + service2.Addieren(val); } catch (Exception e){Console.WriteLine(e.Message);} } } } 13 Beispiel 2: Zustandsbehafteter Addier-Service mit .NET ... namespace AddierService { /// <summary> Webservice addiert Zahl zur bisherigen Summe.</summary> [WebService(Namespace = "http://localhost/")] [SoapRpcService(Use=SoapBindingUse.Encoded] public class Addierer : System.Web.Services.WebService { [WebMethod (EnableSession=true)] public int Addiere(int x) { int s; try { s = (int) Session["Summe"]; } catch (Exception) { s = 0; } s += x; Session["Summe"] = s; return s; } } } 14 Beispiel 2: Client zum zustandsbehafteten .NET-Web-Service using System.Net; ... namespace AddierClientNS { public partial class AddierClient : System.Web.UI.Page{ public void Addiere(object sender, EventArgs ev){ int xval = Convert.ToInt32(x.Text); CookieContainer cookieContainer; if (Session["Cookie"] == null) cookieContainer = new CookieContainer(); else cookieContainer = (CookieContainer)Session["Cookie"]; Addierservice.AddierWebService.Addierer service = new Addierservice.AddierWebService.Addierer(); service.CookieContainer = cookieContainer; result.Text = "Summe: " + service.Addiere(xval); Session["Cookie"] = cookieContainer;} } } 15 Umwandlung zwischen .NET-Typen und XML-Schema-Typen .NET-Typ System.String System.Boolean System.Int16 System.Int32 System.Int64 System.Double System.Byte ... XML-Schema-Typ string boolean short int long double unsignedbyte ... 16 5.4 Web-Services in Java Beispiel: Wetter-Web-Service in Java @Stateless @WebService public class WeatherService{ @WebMethod public int getWeather(String zipcode) { return 23;} } • wird deployed (z.B. in Webcontainer Tomcat) • Annotationen @WebService und @WebMethod an Klasse bzw. Methode • Vor.: stateless (!) Session-Bean (oder Servlet) 17 Zusätzliche Annotationen • Annotation @OneWay an Methode mit Ergebnis void • Klassen-Annotation zur Festlegung des Nachrichtenformats: ? @SOAPBinding(style= ..., use = ...) ? style: SOAPBinding.Style.RPC oder SOAPBinding.Style.DOCUMENT ? use: SOAPBinding.Use.LITERAL oder SOAPBinding.Style.ENCODED 18 Java-Client mit Dependency Injection Beispiel: Stateless Session Bean als Client eines Webservice @Stateless @Resource(name="service/Addierer", type ="javax.jws.WebService", mappedName="AddiererService") public class AddiererClient implements SomeInterface{ public int addiere(int x, int y){ int[] val = {x,y}; @WebServiceRef(name="java:comp/env/service/Addierer") Addierer service; return service.addiere(val);} } } 19 Beispiel: Session-Bean als Web-Service package ejb; import javax.jws.WebService; ... @PermitAll @Stateless @Remote(AddiererIF.class) @WebService(endpointInterface = "ejb.AddiererIF", name = "AddiererIF") @WebContext(contextRoot="/add4WS", secureWSDLAccess=false) public class Addierer implements AddiererIF{ public int addieren(int x, int y) throws RemoteException{ return x+y;} } 20 Beispiel: Interface zur Session-Bean package ejb; import javax.jws.WebService; ... @WebService @SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL) public interface AddiererIF extends Remote { // Umbenennung wegen .NET-Namenskonventionen @WebMethod(operationName="Addieren") public int addieren(int x, int y) throws RemoteException; } 21 Beispiel: Java-Servlet als Web-Service-Client package servlets; import webservicesEJB.*; ... public class AddiererServlet extends HttpServlet { protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); int x = Integer.parseInt(req.getParameter("x")); int y = Integer.parseInt(req.getParameter("y")); int result = 0; try { AddiererService addiererService = new AddiererService(); AddiererServiceSOAP addierer = addiererService.getAddiererServiceSOAP(); result = addierer.addieren(x,y);} catch (Exception e) {e.printStackTrace();} // Ausgabe des Ergebnisses ... }} 22 Erstellen der Proxy-Klassen • die Proxyklassen zum Zugriff auf einen Web-Service (auch .NET) generiert (z.B.) wsimport • wsimport ist in JAX-WS enthalten • Aufruf über die Kommandozeile: 1. (unter Windows:) Start → Ausführen, dann Öffnen: cmd 2. im erscheinenden Fenster mit cd in den gewünschten Ordner gehen 3. wsimport -Xendorsed -keep -extension <URL der WSDL-Datei> 4. z.B. wsimport ... http://localhost:8080/add4WS/Addierer?wsdl 5. das generierte Verzeichnis in den src-Ordner des eclipse-Web-Service-Client-Projekts kopieren