1 / 34

XML, SOAP, Services Web et JAVA Me

XML, SOAP, Services Web et JAVA Me. SOAP Web Services on Smart Clients. Plan. Services Web XML over http SOAP - RPC. Avantages de SOAP. Support pour le typage Plus de 40 types de données avec les schémas XML Permet aux usagers de se définir des types de données complexes

kapila
Download Presentation

XML, SOAP, Services Web et JAVA Me

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. XML, SOAP, Services Web et JAVA Me SOAP Web Services on Smart Clients

  2. Plan • Services Web • XML over http • SOAP - RPC

  3. Avantages de SOAP • Support pour le typage • Plus de 40 types de données avec les schémas XML • Permet aux usagers de se définir des types de données complexes • Messagerie flexible et répandue • Supporte plusieurs schémas de messagerie dont • RPC synchrone, • messages asynchrones, • multicast (souscription), • routage complexe des messages avec plusieurs intermédiaires • Standardisation • Adhérence répandue à SOAP par les services web • Profiter des standards XML qui peuvent être intégrés à SOAP ou utiliser SOAP • WSDL (Web Services Description Language), UDDI (Universal Description, Discovery, and Integration), et la plupart des registres XML; • XML Digital Signature, XML Encryption, SAML (Security Assertion Markup Language) • Rem: sérialisation d’objets Java • En vecteur d’octets en tant qu’élément Base64 pour les transporter par SOAP • Par contre, si on sait que tout se passe en Java, il vaut mieux utiliser RMI ou JMS

  4. Architecture des services web SOAP • J2ME Web Services API (WSA) • Pour tout profil J2ME CDC ou CLDC • remote invocation API • Sous-ensemble strict de J2SE Java API for XML-Based RPC (JAX-RPC 1.1), • + quelques classes Remote Method Invocation (RMI) classes ajoutées pour satisfaire les dépendances de JAX-RPC • Un sous-ensemble strict de SAX, version 2

  5. Organisation d’une application fondée sur JSR

  6. JSR172 run-time et stubs • runtime • Permet aux stubs de réaliser toutes les tâches associées à l’invocation d’un RPC à service web • Déterminer les propriétés spécifiques à une invocation RPC • Décrire les valeurs d’entrée et le résultat d’une invocation RPC • Encoder les valeurs d’entrée • Invoquer le RPC au point de livraison du service web • Décoder et rendre à l’application tout résultat rendu par le service

  7. kSOAP • Construit au-dessus de l’analyseur kXML • http://ksoap2.sourceforge.net/ • Empreinte petite : 41 K pour v2.1.2 • Ne supporte pas la spécification entière de SOAP • L’exemple qui suit est réalisé avec kSOAP v1.2

  8. Analyseur SOAP • Extraire directement les objets Java d’un document SOAP • Type-mapping • Mashalling via un encodage sous forme de chaîne de caractères • Comprends les informations de typage dans un document SOAP • Convertit automatiquement les éléments SOAP en objets Java • Serialisation / désérialisation devient transparente

  9. Exemple simple • Préparer les arguments à transmettre à la méthode distante • Instancier un objet SOAP (SoapObject) • Ajouter les arguments de l’appel addProperty() • Préparer le transport • objet HttpTransport + URL destination • Invoquer la méthode distante • Invocation de la méthode call() sur l’objet HttpTransport • Le résultat est rendu par cette invocation

  10. private String licenseKey = "fVqHySRrXuf"; private String endPointURL ="http://api.google.com/search/beta2"; /** * Simple spell check using convenience class HttpTransport * This function returns the Google suggested spell. * @param query the string to be spell corrected. */ public String spellCheck (String query) throws Exception { // Prepare request SOAP message in a memory object SoapObject method = new SoapObject("urn:GoogleSearch", "doSpellingSuggestion"); method.addProperty("key", licenseKey); method.addProperty("phrase", query); // Prepare SOAP RPC call object. HttpTransport rpc = new HttpTransport(endPointURL); // Google uses 1999 SOAP standards. ClassMap cm = new ClassMap(Soap.VER10); rpc.setClassMap (cm); // Conduct RPC call through HTTP and directly get results String spellSugg = (String) rpc.call (method); System.out.println(rpc.requestDump); System.out.println(rpc.responseDump); return spellSugg; }

  11. Fonctionnement de la méthode ‘call’ 1- Sérialisation de l’objet SoapObject sous forme de message de requête avec les bons espaces de noms <?xml version='1.0' encoding='UTF-8'?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body> <ns1:doSpellingSuggestion xmlns:ns1="urn:GoogleSearch" SOAP-ENV:encodingStyle= "http://schemas.xmlsoap.org/soap/encoding/"> <key xsi:type="xsd:string">QLgFCbGCQD6710PlS</key> <phrase xsi:type="xsd:string">phon</phrase> </ns1:doSpellingSuggestion> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

  12. Fonctionnement de la méthode ‘call’ • 2. soumission de la requête au point de livraison à travers HTTP • 3. récupération du message de réponse SOAP <?xml version='1.0' encoding='UTF-8'?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body> <ns1:doSpellingSuggestionResponse xmlns:ns1="urn:GoogleSearch" SOAP-ENV:encodingStyle= "http://schemas.xmlsoap.org/soap/encoding/"> <return xsi:type="xsd:string">phone</return> </ns1:doSpellingSuggestionResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope> • 4. transformer la réponse en objet Java et rendre cet objet • La chaîne « phone » de type String

  13. Transport des message en kSOAP package org.ksoap.transport; import java.io.*; import javax.microedition.io.*; import org.kxml.*; import org.kxml.io.*; import org.kxml.parser.*; import org.ksoap.*; public class HttpTransport { String url; String soapAction = "\"\""; SoapEnvelope requestEnvelope = new SoapEnvelope (); SoapEnvelope responseEnvelope = new SoapEnvelope (); HttpConnection connection; OutputStream os; InputStream is; InputStreamReader reader;

  14. Transport des message en kSOAP /** Sends the requestEnvelope and fills the responseEnvelope @exception InterruptedIOException if transport was closed async. @exception IOException if an error occurs */ public void call () throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream (); XmlWriter xw = new XmlWriter (new OutputStreamWriter (bos)); requestEnvelope.write (xw); xw.flush (); bos.write ('\r'); bos.write ('\n'); byte [] requestData = bos.toByteArray (); bos = null; xw = null; requestDump = debug ? new String (requestData) : null; responseDump = null;

  15. try { connected = true; connection = (HttpConnection) Connector.open (url, Connector.READ_WRITE, true); connection.setRequestProperty ("SOAPAction", soapAction); connection.setRequestProperty ("Content-Type", "text/xml"); connection.setRequestProperty ("Content-Length", ""+requestData.length); connection.setRequestProperty ("User-Agent", "kSOAP/1.0"); connection.setRequestMethod (HttpConnection.POST); os = connection.openOutputStream (); os.write (requestData, 0, requestData.length); os.close (); requestData = null; is = connection.openInputStream (); reader = new InputStreamReader (is); XmlParser xp = new XmlParser (reader); responseEnvelope.parse (xp); } finally { if (!connected) throw new InterruptedIOException (); reset (); } }

  16. Génération des stubs • IBM WebSphere Studio Device Developer • SunOne Studio • CodeWarrior Wireless Studio

  17. Fonctionnement interne de kSOAP v 1.2 • Lorsque l’analyseur kSOAP rencontre un élément SOAP, l’analyseur lit l’élément XML dans un objet Java selon les règles suivantes: • Si l’élément SOAP est un des type primitifs prédéfini du tableau, il est converti dans un objet Java du type correspondant • Si l’élément SOAP n’a pas de fils, mais n’est pas un des types prédéfini, il est converti en un objet SoapPrimitive • On peut récupérer les informations de typage de l’élément originel SOAP via les méthodes SoapPrimitive.getNameSpace() et SoapPrimitive.getName() • On peut accéder la valeur de la chaîne de caractères via la méthode SoapPrimitive.toString() • Si l’élément SOAP a des fils, i.e. c’est un élément complexe, il est converti en objet implémentant l’interface KvmSerializable • La classe utilitaire SoapObject implémente cet interface • On peut récupérer les information s typages via les méthodes SoapObject.getNameSpace() et SoapObject.getName() • Les fils d’un élément complexe sont convertis en propriétés de leur parent SoapObject selon les règles précédentes. • Chaque propriété possède se voit aussi associé un objet PropertyInfo qui contient les informations comme le nom de l’élément SOAP et son type Java

  18. Structure des SoapObject • Parce qu’un objet SoapObject peut avoir des propriétés SoapObject, on peut l’utiliséer pour représenter des structures hiérarchiques complexes

  19. Sérialiser un objet • Pour sérialiser un objet • Construire une représentaiton hiérarchique où • Toutes les feuilles doivent être soit un objet SoapPrimitive, soit un des quatre types prédéfinis • La racine par contre ne possède pas de paires (SoapObject, PropertyInfo), on a donc perdu en principe le nom de la racine lors de l’analyse • Utiliser un objet « writer » kSOAP pour sérialiser l’objet en mémoire dans un flot XML

  20. // SoapObject "method" is the calling construct // // the "" and "StockOrderParameters" here are // element name/namespace rather than SOAP type name/namespace SoapObject method = new SoapObject("", "StockOrderParameters"); method.addProperty("Symbol", "XYZ"); method.addProperty("From", "Michael Yuan"); method.addProperty("Shares", new Integer (1000)); method.addProperty("Buy", new Boolean (true)); method.addProperty("LimitPrice", new SoapPrimitive ("http://www.w3.org/2001/XMLSchema", "float", "123.4")); // Assemble "method" into an enveloped SOAP message // and then export to a String ByteArrayOutputStream bos = new ByteArrayOutputStream (); XmlWriter xw = new XmlWriter (new OutputStreamWriter (bos)); // Use default mapping between Java objects and Soap elements SoapEnvelope envelope = new SoapEnvelope (new ClassMap (Soap.VER12)); envelope.setBody (method); envelope.write (xw); xw.flush (); bos.write ('\r'); bos.write ('\n'); byte [] requestData = bos.toByteArray (); String requestSOAPmesg = new String (requestData);

  21. Requête <SOAP-ENV:Envelope xmlns:SOAP-ENC="http://www.w3.org/2001/12/soap-encoding" xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body SOAP-ENV:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> <StockOrderParameters id="o0" SOAP-ENC:root="1"> <Symbol xsi:type="xsd:string">XYZ</Symbol> <From xsi:type="xsd:string">Michael Yuan</From> <Shares xsi:type="xsd:int">1000</Shares> <Buy xsi:type="xsd:boolean">true</Buy> <LimitPrice xsi:type="xsd:float">123.45</LimitPrice> </StockOrderParameters> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

  22. Réponse

  23. Récupérer les éléments de la réponse ByteArrayInputStream bis = new ByteArrayInputStream (soapRespMesg.getBytes ()); InputStreamReader reader = new InputStreamReader (bis); XmlParser xp = new XmlParser (reader); // Use default mapping between Java objects and Soap elements. SoapEnvelope envelope = new SoapEnvelope (new ClassMap (Soap.VER12)); envelope.parse (xp); // Get the parsed structure. SoapObject orderStatus = (SoapObject) envelope.getResult(); // Retrieve the values as appropriate Java objects. String customerName = (String) orderStatus.getProperty ("CustomerName"); String symbol = (String) orderStatus.getProperty ("Symbol"); Integer share = (Integer) orderStatus.getProperty ("Share"); Boolean buy = (Boolean) orderStatus.getProperty ("Buy"); // Since the default mapping table has no "Float" type, there is no corresponding // Java object type for "xsd:float". So, as any unknown type, // this element is mapped to a "SoapPrimitive". SoapPrimitive price = (SoapPrimitive) orderStatus.getProperty ("Price"); SoapPrimitive execTime = (SoapPrimitive) orderStatus.getProperty ("ExecTime");

  24. Automatiser la sérialisation / désérialisation • Indiquer à l’analyseur la relation entre les type SOAP et les types Java • Compléter la table de base • Indiquer à l’analyseur comment convertir les chaînes de caractères en objet Java • Enregistrer dans la table un objet Marshal qui sait faire la conversion public interface Marshal { public Object readInstance ( SoapParser parser, String namespace, String name, ElementType expected) throws IOException; public void writeInstance (SoapWriter writer, Object instance) throws IOException; public void register (ClassMap cm); }

  25. La classe utilitaire org.ksoap.marshal.MarshalDate Public class MarshalDate implements Marshal public Object readInstance ( SoapParser parser, String namespace, String name, ElementType expected) throws IOException { parser.parser.read (); // Start tag Object result = IsoDate.stringToDate ( parser.parser.readText (), IsoDate.DATE_TIME); parser.parser.read (); // End tag return result; } public void register (ClassMap cm) { cm.addMapping (cm.xsd, "dateTime", MarshalDate.DATE_CLASS, this); }

  26. ClassMap.addMapping /** Defines a direct mapping from a namespace and name to a Java class (and vice versa), using the given marshal mechanism */ public void addMapping (String namespace, String name, Class clazz, Marshal marshal) { qNameToClass.put ( new SoapPrimitive (namespace, name, null), marshal == null ? (Object) clazz : marshal); classToQName.put ( clazz.getName (), new Object [] {namespace, name, null, marshal}); if (prefixMap.getPrefix (namespace) == null) prefixMap = new PrefixMap (prefixMap, "n"+(cnt++), namespace); }

  27. Ajout à la table des mappings avant de désérialiser la réponse ByteArrayInputStream bis = new ByteArrayInputStream (mesg.getBytes ()); InputStreamReader reader = new InputStreamReader (bis); XmlParser xp = new XmlParser (reader); // Register Marshal for "xsd:dateTime" type ClassMap cm = new ClassMap (Soap.VER12); Marshal md = new MarshalDate (); md.register (cm); SoapEnvelope envelope = new SoapEnvelope (cm); envelope.parse (xp); SoapObject orderStatus =(SoapObject)envelope.getResult(); Date execTime = (Date) orderStatus.getProperty ("ExecTime");

  28. La sérialisation des « array »

  29. La désérialisation sous forme de Vector // Register Marshal for "xsd:dateTime" type ClassMap cm = new ClassMap (Soap.VER12); Marshal md = new MarshalDate (); md.register (cm); SoapEnvelope envelope = new SoapEnvelope (cm); envelope.parse (xp); SoapObject orderStatus = (SoapObject) envelope.getResult(); String customerName = (String) orderStatus.getProperty ("CustomerName"); Vector transactions = (Vector) orderStatus.getProperty ("Transactions"); // First element in the array SoapObject transaction0 = (SoapObject) transactions.elementAt(0); String symbol0 = (String) transaction0.getProperty ("Symbol"); Integer share0 = (Integer) transaction0.getProperty ("Share"); Boolean buy0 = (Boolean) transaction0.getProperty ("Buy"); SoapPrimitive price0 = (SoapPrimitive) transaction0.getProperty ("Price"); // Second element in the array SoapObject transaction1 = (SoapObject) transactions.elementAt(1); String symbol1 = (String) transaction1.getProperty ("Symbol"); Integer share1 = (Integer) transaction1.getProperty ("Share"); Boolean buy1 = (Boolean) transaction1.getProperty ("Buy"); SoapPrimitive price1 = (SoapPrimitive) transaction1.getProperty ("Price");

  30. Validation des documents à l’aide des templates SOAP • Via la classe ClassMap • Ajouter un objet template SoapObject à l’analyseur • Template • un SoapObject vide avec de l’information sur • le type SOAP parent • Les noms des éléments des enfants (properties) • Leur type Java • Un fils peut lui-même être un template ce qui permet de construire des templates arbitrairement complexes • Si l’analyseur détecte une erreur, alors il lance une exception et s’arrête

  31. Une transaction doit contenir xsd:string value Symbol, xsd:int value Share, xsd:boolean value Buy, xsd:float value Price ByteArrayInputStream bis = new ByteArrayInputStream (arraySoapRespMesg.getBytes ()); InputStreamReader reader = new InputStreamReader (bis); XmlParser xp = new XmlParser (reader); ClassMap cm = new ClassMap (Soap.VER12); // Register Marshal for "xsd:dateTime" type Marshal md = new MarshalDate (); md.register (cm); SoapObject so = new SoapObject ("http://www.javaworld.com/ksoap/test", "transaction"); so.addProperty ("Symbol", new String ("")); so.addProperty ("Share", new Integer (0)); so.addProperty ("Buy", new Boolean (true)); so.addProperty ("Price", new SoapPrimitive ("xsd", "float", "")); cm.addTemplate (so); SoapEnvelope envelope = new SoapEnvelope (cm); envelope.parse (xp); SoapObject orderStatus = (SoapObject) envelope.getResult();

  32. Comparaison entre le package J2ME Web Services Optional Package et kXML + kSOAP • Modèle de traitement XML • J2ME Web Services Optional Package • SAX seulement • kXML • SAX, XMLPull et kDOM • Centré Java ou centré XML • J2ME Web Services Optional Package • Traite SOAP RPC de manière similaire à RMI RPC • Pas de contrôle sur les messages • kXML • Plus de prise sur la structure XML interne

  33. Références • Enterprise J2ME • Chapitre 16 • Access Web services from wireless devices, Handle SOAP messages on MIDP devices using kSOAP • http://www.javaworld.com/javaworld/jw-08-2002/jw-0823-wireless.html?page=1

More Related