MII 733 Computación Móvil José Miguel Rubio L. Oficina 3-20 http://www.inf.ucv.cl/~jrubio jose.rubio.l@ucv.cl Sección 5 Servicios Web con Axis José Miguel Rubio L. Oficina 3-20 http://www.inf.ucv.cl/~jrubio jose.rubio.l@ucv.cl Introducción I Los Servicios Web son la piedra angular de cualquier desarrollo de sistemas distribuidos actual Los ordenadores hablan unos a otros a través de la web usando HTTP y otros protocolos. Un servicio web no tiene interfaz gráfica Provee una API de métodos que pueden ser invocados en la web Diseñados para proveer “servicios” Introducción II Futuro en el que los negocios exponen aplicaciones a clientes como Servicios Web en los cuales se paga por su uso Los sistemas de diferentes empresas cooperan unos con otros a través de la Web Mientras que DCOM está basado en estándares propietarios, los Servicios Web lo están en XML y HTTP Son independientes de la plataforma y del lenguaje como CORBA, pero más aceptados En .NET, IIS y la infraestructura ASP.NET compilan las fuentes, construyen contratos WSDL y manejan las peticiones y respuestas de los servicios web. En Java AXIS realiza una tarea muy similar SOA Los servicios web han dado lugar a un nuevo modo de diseñar sistemas distribuídos: SOA = colección de servicios Arquitecturas SOA (Service Oriented Arquitecture) Más información en http://www.servicearchitecture.com/ http://msdn.microsoft.com/Longhorn/understandin g/pillars/Indigo/default.aspx?pull=/library/enus/dnbda/html/srorientwp.asp Servicios Web Son un estándar basado en protocolos abiertos como HTTP y SOAP SOAP es un vocabulario XML que representa RPCs http://www.w3.org/TR/SOAP No necesitas ni Windows ni .NET, ni UNIX ni Java para escribir servicios web Servicio web = aplicación que: se ejecuta en un servidor web expone métodos a clientes escucha peticiones HTTP representando comandos que invocan a métodos Web ejecuta métodos web y devuelve resultados SOAP SOAP es un protocolo de comunicación basado en XML útil para la comunicación entre aplicaciones Actualmente en versión 1.2, aunque la más utilizada es la 1.1 SOAP es reconocido como el backbone de una nueva generación de aplicaciones multi-platforma y multi-lenguaje, denominado Servicios Web. SOAP es un mecanismo para el intercambio de mensajes a través de Internet independiente de los lenguajes de programación http://www.w3.org/2000/xp/Group/ Es un protocolo de transporte Los clientes envían una petición SOAP mediante un HTTP POST normalmente y reciben un código de respuesta (éxito o error) y una respuesta SOAP Un mensaje SOAP es un mensaje XML que consta de un conjunto de cabeceras opcionales y de un cuerpo. Petición SOAP <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/so ap/envelope/"> <soap:Body> <getProductDetails xmlns="http://warehouse.example.com/ws"> <productId>827635</productId> </getProductDetails> </soap:Body> </soap:Envelope> Respuesta SOAP <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <getProductDetailsResponse xmlns="http://warehouse.example.com/ws"> <getProductDetailsResult> <productName>Toptimate 3-Piece Set</productName> <productId>827635</productId> <description>3-Piece luggage set. Black Polyester.</description> <price>96.50</price> <inStock>true</inStock> </getProductDetailsResult> </getProductDetailsResponse> </soap:Body> </soap:Envelope> Apache AXIS AXIS es un motor SOAP, una framework para construir tanto la parte servidora como cliente de Servicios Web. Además: Incluye un servidor Un servlet que se integra con motores de servlets como Tomcat Soporte extensivo del estándar Web Service Description Language (WSDL) Una herramienta para generar clases Java a partir de WSDL Un conjunto de aplicaciones de ejemplo Una herramienta para la monitorización de los paquetes TCP/IP Open source, disponible en: http://ws.apache.org/axis/ WS-* Apache Axis Axis es disponible en el fichero axis.jar; que implementa la API JAX-RPC API declarada en los ficheros JAR jaxrpc.jar y saaj.jar. Requiere varias bibliotecas de ayuda, para logeo, procesamiento WSDL e introspección. Características AXIS La arquitectura de AXIS está basada en cadenas configurables de manejadores de mensajes que implementan pequeños fragmentos de funcionalidad de una manera flexible Sus propiedades principales: Rápido implementado con un procesador XML SAX Flexible Estable Orientado a Compontes Soporta WSDL 1.1 Apache EXtensible Interaction System (AXIS) motor SOAP muy configurable Proceso de Generación de Programas con Axis Instalación Axis 1. Bajarse la distribución de Apache Axis de http://ws.apache.org/axis/ La versión actual es 1.2RC2 2. 3. 4. Bajarse tanto versión binaria (ya compilado) como fuente (contiene ejemplos) Instalar un contenedor de servlets como Tomcat 5 Copiar el directorio axis-1_2RC2\webapps\axis contenido en la distribución de Axis en %TOMCAT_HOME\webapps Instalar .jar terceros necesitados por Axis, copiándolos en %TOMCAT_HOME%\common\lib: Junit.jar (Junit Testing System http://www.junit.org/index.htm) mail.jar (Java Mail http://java.sun.com/products/javamail/) activation.jar (Java Beans Activation Framework http://java.sun.com/products/javabeans/glasgow/jaf.html) Instalación Axis 5. 6. 7. Arrancar el servidor web Validar la instalación: http://127.0.0.1:8080/axis/ (hacer clic en Validate) Validar un SOAP endpoint: http://localhost:8080/axis/s ervices/Version?method=getVe rsion Axis soporta HTTP GET Creando Servicios Web .jws Axis tiene un método muy sencillo de crear servicios web básicos, mediante el mecanismo de ficheros .jws Cuando alguien solicita a través de una url un fichero .jws, éste es compilado y ejecutado Revisar ejemplo: http://localhost:8080/axis/Echo Headers.jws?method=list Cómo Instalar un Nuevo Servicio Web Dos pasos: 1. Copiar el código del servicio web bajo el directorio %TOMCAT_HOME%\webapps\axis WAR 2. En el directorio WEB-INF\classes de AXIS copiar las clases de tu nuevo servicio web Si tus clases están en un .jar simplemente copiarlas a WEB-INF\lib Informar al motor de AXIS acerca del nuevo fichero Se realiza haciendo un POST de un fichero de explotación (wsdd) mediante el programa AdminClient El Web Service Deployment Descriptor describe en XML cuál es el servicio web y qué métodos exporta Compilando Servicios Web Para compilar servicios web necesitamos colocar en nuestro CLASSPATH las dependencias de AXIS set AXIS_HOME=c:\axis set AXIS_LIB=%AXIS_HOME%\lib set AXISCLASSPATH=%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons -discovery.jar;%AXIS_LIB%\commonslogging.jar;%AXIS_LIB%\jaxrpc.jar;%AXIS_LIB%\saaj.ja r;%AXIS_LIB%\log4j-1.2.8.jar;%AXIS_LIB%\xmlapis.jar;%AXIS_LIB%\xercesImpl.jar Luego podemos hacer: javac –classpath %AXISCLASSPATH% java -cp %AXISCLASSPATH% ... Ejecución del AdminClient Buscar en axis\samples\stock un ejemplo de un fichero de explotación web de AXIS: deploy.wsdd. Registrar el servicio web mediante el comando: java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient lhttp://localhost:8080/axis/services/AdminServi ce deploy.wsdd Para probar el servicio web acceder a: java -cp .;%AXISCLASSPATH% samples.stock.GetQuote lhttp://localhost:8080/axis/servlet/AxisServlet -uuser1 -wpass1 XXX Cómo Añadir AXIS a tu Aplicación Web Los pasos a seguir son: 1. 2. 3. 4. Añadir axis.jar, wsdl.jar, saaj.jar, jaxrpc.jar y otras bibliotecas dependientes a tu fichero WAR Copiar todas las declaraciones del servlet de Axis y sus mapeos de axis/WEB-INF/web.xml y añadirlos a tu propio web.xml Construir y desplegar la aplicación web Ejecutar el AdminClient de AXIS contra tu propia aplicación web, en vez de contra AXIS, cambiando la url con la que invocas a AXIS Consumiendo un Servicio Web Vamos a desarrollar una pequeña aplicación cliente que consume el servicio web más sencillo que podemos imaginar, implementado en Echo.jws, que copiaremos a %TOMCAT_HOME%\webapps\AXIS\: public class Echo { public String echoString(String msg) { return msg; } } Consumiendo un Servicio Web A continuación, vamos a definir un cliente que me permita consumir este servicio web desde línea de comando Desde un navegador podríamos invocar a este servicio mediante la URL: http://localhost:8080/axis/Echo.jws?method=ec hoString&msg=hola Consumiendo un Servicio Web import org.apache.axis.client.Call; import org.apache.axis.client.Service; import javax.xml.namespace.QName; public class EchoClient { public static void main(String [] args) { try { String endpoint = "http://localhost:8080/axis/Echo.jws"; Service service = new Service(); Call call = (Call) service.createCall(); service.createCall(); call.setTargetEndpointAddress( call.setTargetEndpointAddress( new java.net.URL(endpoint) java.net.URL(endpoint) ); call.setOperationName(new QName("http://soapinterop.org/", QName("http://soapinterop.org/", "echoString "echoString") echoString") ); String ret = (String) call.invoke( call.invoke new Object[] { "Hello!" } ); System.out.println("Sent 'Hello!', got '" + ret + "'"); } catch (Exception e) { System.err.println(e.toString()); } } } Consumiendo un Servicio Web Los objetos Service y Call son los objetos estándar JAX-RPC que permiten guardar metadatos sobre el servicio a invocar. Consumiendo un Servicio Web Al invocar el método la siguiente información aparecería en el navegador: <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <SOAP-ENV:Body> <ns1:echoString xmlns:ns1="http://soapinterop.org/"> <arg0 xsi:type="xsd:string">Hello!</arg0> </ns1:echoString> </SOAP-ENV:Body> </SOAP-ENV:Envelope> Consumiendo un Servicio Web Si deseamos dar nombre a los parámetros solamente deberemos insertar el siguiente código: // Call to addParameter/setReturnType as described in user-guide.html call.addParameter("testParam", org.apache.axis.Constants.XSD_STRING, javax.xml.rpc.ParameterMode.IN); Si queremos indicar a AXIS cuál es el tipo de dato devuelto haríamos: call.setReturnType(org.apache.axis.Constants.XSD_ STRING); Publicando un Servicio Web con AXIS Vamos a suponer que tenemos una clase Calculator que queremos sea accesible como Servicio Web. Tenemos dos mecanismos: través de un fichero .JWS Registrando el nuevo servicio vía AxisAdmin usando desplegamiento propietario A Publicando con JWS Sólo para Servicios Web muy sencillos Con esta instrucción se desplegaría: copy Calculator.java <your-webapproot>/axis/Calculator.jws Para invocarlo haríamos: http://localhost:8080/axis/Calculator.jws O nos crearíamos nuestros clientes propietarios. Revisar samples/userguide/example2/Calculator.java Calculator.java public class Calculator { public int add(int i1, int i2) { return i1 + i2; } public int subtract(int i1, int i2) { return i1 - i2; } } CalcClient.java import import import import org.apache.axis.client.Call; org.apache.axis.client.Service; org.apache.axis.encoding.XMLType; org.apache.axis.utils.Options; import javax.xml.rpc.ParameterMode; public class CalcClient { public static void main(String [] args) throws Exception { Options options = new Options(args); String endpoint = "http://localhost:" + options.getPort() + "/axis/Calculator.jws"; args = options.getRemainingArgs(); if (args == null || args.length != 3) { System.err.println("Usage: CalcClient <add|subtract> arg1 arg2"); return; } String method = args[0]; if (!(method.equals("add") || method.equals("subtract"))) { System.err.println("Usage: CalcClient <add|subtract> arg1 arg2"); return; } CalcClient.java Integer i1 = new Integer(args[1]); Integer i2 = new Integer(args[2]); Service Call service = new Service(); call = (Call) service.createCall(); call.setTargetEndpointAddress( new java.net.URL(endpoint) ); call.setOperationName( method ); call.addParameter( "op1", XMLType.XSD_INT, ParameterMode.IN ); call.addParameter( "op2", XMLType.XSD_INT, ParameterMode.IN ); call.setReturnType( XMLType.XSD_INT ); Integer ret = (Integer) call.invoke( new Object [] { i1, i2 }); System.out.println("Got result : " + ret); } } Custom Deployment Habrá ocasiones en que queramos exportar código anteriormente realizado como un servicio web Además a menudo se requerirán configuraciones más sofisticadas: inclusión de Handlers Para acceder a toda la flexibilidad configurativa de AXIS necesitamos utilizar Web Service Deployment Descriptor (WSDD) Web Service Deployment Descriptor Describe un conjunto de configuraciones que quieres hacer disponible a AXIS Por ejemplo: <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" > <service name="MyService" provider="java:RPC"> <parameter name="className" value="samples.userguide.example3.MyService"/> <parameter name="allowedMethods" value="*"/> </service> </deployment> Indicamos que el servico web MyService de tipo java:RPC es definido en la clase samples.userguide.example3.MyService y hacemos disponibles todos los métodos públicos en esa clase Web Service Deployment Descriptor Algunas opciones adicionales que se pueden especificar en un .wsdd son: Alcance de los servicios, se pueden definir servicios web con tres alcances: request crea un nuevo objeto cada vez que se recibe una petición al servicio application un solo objeto servirá todas las peticiones session un objeto por cada sesión de cliente Por ejemplo: <service name="MyService"...> <parameter name="scope" value=“request"/> ... </service> Utilizando el AdminClient La clase org.apache.axis.client.AdminClient permite el envío del fichero de explotación al servidor Tomcat, si está escuchando en un puerto diferente al 8080 hay que enviar el parámetro –p <port>. java org.apache.axis.client.AdminClient deploy.wsdd java org.apache.axis.client.AdminClient list java org.apache.axis.client.AdminClient undeploy.wsdd Revisar samples/userguide/example3. Manejadores y Cadenas Los Handlers (o manejadores) permiten pre/post procesar peticiones a servicios web. Por ejemplo, para contar el número de invocaciones recibidas Revisar ejemplo samples/log En el .wsdd podemos colocar un elemento handler que puede recibir una serie de parámetros (subelemento parameter) Después, podemos definir services que usan los handler, mediante subelementos requestFlow del service Estos handlers son invocados antes de que el provider sea invocado Manejadores y Cadenas <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"> <!-- define the logging handler configuration --> <handler name="track" type="java:samples.userguide.example4.LogHandler"> <parameter name="filename" value="MyService.log"/> </handler> <!-- define the service, using the log handler we just defined --> <service name="LogTestService" provider="java:RPC"> <requestFlow> <handler type="track"/> </requestFlow> <parameter name="className" value="samples.userguide.example4.Service"/> <parameter name="allowedMethods" value="*"/> </service> </deployment> Pasos para Crear un Servicio Web con Custom Deployment 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Crear un directorio de trabajo: examples/webservices/ej3customdeployment Crear la clase Java que define el servicio web (MyService.java) Crear el cliente web (Client.java) Crear el descriptor de despliegue para este servicio (deploy.wsdd) Crear el descriptor para eliminar este servicio (undeploy.wsdd) cd ej3customdeployment Compilar el código: javac *.java Ejecutar el AdminClient: java org.apache.axis.client.AdminClient deploy.wsdd copy ej3customdeployment/*.class %TOMCAT_HOME%\axis\WEBINF\classes\ ej3customdeployment Ejecutar: cd ..; java ej3customdeployment.Client lhttp://localhost:8080/axis/services/MyService "test me!" MyService.java package ej3customdeployment; public class MyService { public String serviceMethod(String arg) { return arg; } } Client.java package ej3customdeployment; import org.apache.axis.client.Call; import org.apache.axis.client.Service; import org.apache.axis.encoding.XMLType; import org.apache.axis.utils.Options; import javax.xml.namespace.QName; import javax.xml.rpc.ParameterMode; public class Client { public static void main(String [] args) { try { Options options = new Options(args); String endpointURL = options.getURL(); String textToSend; args = options.getRemainingArgs(); if ((args == null) || (args.length < 1)) { textToSend = "<nothing>"; } else { textToSend = args[0]; } Service service = new Service(); Call call = (Call) service.createCall(); call.setTargetEndpointAddress( new java.net.URL(endpointURL) ); call.setOperationName( new QName("http://ej3_customdeployment", "serviceMethod") ); call.addParameter( "arg1", XMLType.XSD_STRING, ParameterMode.IN); call.setReturnType( org.apache.axis.encoding.XMLType.XSD_STRING ); String ret = (String) call.invoke( new Object[] { textToSend } ); System.out.println("You typed : " + ret); } catch (Exception e) { System.err.println(e.toString()); } } } deploy.wsdd/undeploy.wsdd deploy.wsdd <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" > <service name="MyService" provider="java:RPC"> <parameter name="className" value="ej3customdeployment.MyService"/> <parameter name="allowedMethods" value="*"/> </service> </deployment> undeploy.wsdd <undeployment xmlns="http://xml.apache.org/axis/wsdd/"> <service name="MyService"/> </undeployment> Mapeos de WSDL a Java xsd:base64Binary byte[] xsd:boolean boolean xsd:byte byte xsd:dateTime java.util.Calendar xsd:decimal java.math.BigDecimal xsd:double double xsd:float float xsd:hexBinary byte[] xsd:int int xsd:integer java.math.BigInteger xsd:long long xsd:QName javax.xml.namespace.QName xsd:short short xsd:string java.lang.String Pasando Objetos en Servicios Web Las excepciones se representan como elementos wsdl:fault Podemos pasar objetos como argumentos con la ayuda del elemento del elemento beanmapping en un .wsdd <beanMapping qname="ns:local" xmlns:ns="someNamespace" languageSpecificType="java:my.java.thingy"/> Revisar ejemplo: samples/userguide/example5/BeanService.java <deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/ja va"> <service name="OrderProcessor" provider="java:RPC"> <parameter name="className" value="samples.userguide.example5.BeanService"/> <parameter name="allowedMethods" value="processOrder"/> <beanMapping qname="myNS:Order" xmlns:myNS="urn:BeanService" languageSpecificType="java:samples.userguide.example5.Or der"/> </service> </deployment> Pasando Objetos en Servicios Web Dado que el BeanSerializer no permite transformar clases ya existentes que no conformen con el estándar JavaBean, es posible utilizar custom serialization Para ello en el wsdd colocaremos: <typeMapping qname="ns:local" xmlns:ns="someNamespace" languageSpecificType="java:my.java.thingy" serializer="my.java.Serializer" deserializer="my.java.DeserializerFactory" encodingStyle="http://schemas.xmlsoap.org/so ap/encoding/"/> Web Services Description Language (WSDL) Si miramos al fichero WSDL encontraremos: service que describe el servicio web Elementos operation que documentan las operaciones Elementos binding que documentan los protocolos soportados por el servicio web Etc. Elemento Para publicar un servicio web deberemos publicar su contrato, WSDL. Otros desarrolladores pueden utilizar el contrato para desarrollar clientes web Nomalmente procesan el fichero WSDL a través de una herramienta que genera clases wrapper Usando WSDL con Axis Web Service Description Language (WSDL) permite describir los servicios web de una manera estructurada Un WSDL nos da la siguiente información: La interfaz al servicio Los parámetros que acepta La localización del servicio AXIS soporta WSDL de tres formas: Podemos obtener el wsdl de un servicio accediendo a su URL en un navegador y colocando el sufijo ?wsdl http://localhost:8080/axis/Echo.jws?wsdl Herramienta WSDL2Java que genera Java proxies y skeletons a partir de descriptores WSDL Herramienta Java2WSDL que construye WSDL a partir de clases Java WSDL2Java: proxies, stubs y tipos de datos Esta herramienta es disponible en la clase: org.apache.axis.wsdl.WSDL2Java Su uso sería: java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL) Existe la tarea wsdl2java en Ant WSDL2Java WSDL clause Java class(es) generated For each entry in the type section A java class A holder if this type is used as an inout/out parameter For each portType A java interface For each binding A stub class For each service A service interface A service implementation (the locator) Mapeo Tipos <xsd:complexType name="phone"> <xsd:all> <xsd:element name="areaCode" type="xsd:int"/> <xsd:element name="exchange" type="xsd:string"/> <xsd:element name="number" type="xsd:string"/> </xsd:all> </xsd:complexType> Mapearía a: public class Phone implements java.io.Serializable { public Phone() {...} public int getAreaCode() {...} public void setAreaCode(int areaCode) {...} public java.lang.String getExchange() {...} public void setExchange(java.lang.String exchange) {...} public java.lang.String getNumber() {...} public void setNumber(java.lang.String number) {...} public boolean equals(Object obj) {...} public int hashCode() {...} } Mapeo Parámetros de Entrada/Salida package samples.addr.holders; public final class PhoneHolder implements javax.xml.rpc.holders.Holder { public samples.addr.Phone value; public PhoneHolder() { } public PhoneHolder(samples.addr.Phone value) { this.value = value; } } Mapeo PortTypes <message name="empty"> <message name="AddEntryRequest"> <part name="name" type="xsd:string"/> <part name="address" type="typens:address"/> </message> <portType name="AddressBook"> <operation name="addEntry"> <input message="tns:AddEntryRequest"/> <output message="tns:empty"/> </operation> </portType> Mapearía a: public interface AddressBook extends java.rmi.Remote { public void addEntry(String name, Address address) throws java.rmi.RemoteException; } Mapeo Bindings Su nombre es el nombre del Binding con el sufijo Stub Implementa el SDI (Service Description Interface) Actúa como un proxy entre el cliente y el servicio web El stub esconde el endpoint, namespace, o los arrays de parámetros Así el siguiente fragmento de wsdl generaría: <binding name="AddressBookSOAPBinding" type="tns:AddressBook"> ... </binding> Lo siguiente: public class AddressBookSOAPBindingStub extends org.apache.axis.client.Stub implements AddressBook { public AddressBookSOAPBindingStub() throws org.apache.axis.AxisFault {...} public AddressBookSOAPBindingStub(URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {...} public AddressBookSOAPBindingStub(javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {...} public void addEntry(String name, Address address) throws RemoteException {...} } Servicios Normalmente un cliente instanciará un localizador de servicios y luego llamará al método get para recuperar su stub. Se deriva del elemento service de WSDL: <service name="AddressBookService"> <port name="AddressBook" binding="tns:AddressBookSOAPBinding"> <soap:address location="http://localhost:8080/axis/services/AddressBook"/> </port> </service> Como: public interface AddressBookService extends javax.xml.rpc.Service { public String getAddressBookAddress(); public AddressBook getAddressBook() throws javax.xml.rpc.ServiceException; public AddressBook getAddressBook(URL portAddress) throws javax.xml.rpc.ServiceException; } WSDL2Java will also generate the locator which implements this interface: public class AddressBookServiceLocator extends org.apache.axis.client.Service implements AddressBookService { ... Uso del Service Locator public class Tester { public static void main(String [] args) throws Exception { // Make a service AddressBookService service = new AddressBookServiceLocator(); SDI. // Now use the service to get a stub which implements the AddressBook port = service.getAddressBook(); // Make the actual call Address address = new Address(...); port.addEntry("Russell Butek", address); } } Bindings en la Parte Servidora: Skeleton Stub es el proxy en el cliente de un Servicio Web El Skeleton es el proxy del Servicio Web en el servidor Necesitas especificar los flags --server-side --skeletonDeploy true" cuando invocas WSDL2java: java org.apache.axis.wsdl.WSDL2Java -server-side --skeletonDeploy true AddressBook.wsdl Bindings en la Parte Servidora: Skeleton WSDL clause For each binding Java class(es) generated A skeleton class An implementation template class For all services One deploy.wsdd file One undeploy.wsdd file Los Skeleton Intermediario entre el Axis engine y la implementación del servicio Su nombre es el del binding con el sufijo Skeleton Compilación Ejemplo ej4wsdl2java Los pasos a seguir serían: java org.apache.axis.wsdl.WSDL2Java -server-side AddressBook.wsdl cd AddressFetcher2 javac *.java java org.apache.axis.client.AdminClient deploy.wsdd Herramienta Java2WSDL 1. Crear una interfaz Java o una clase que describa la interfaz del servicio web. Por ejemplo: package ej5java2wsdl; public interface MyWidgetPrice { public void setWidgetPrice(String widgetName, String price); public String getWidgetPrice(String widgetName); } Herramienta Java2WSDL 2. Crear el WSDL por medio de Java2WSDL Para crear el WSDL asociado a la clase anterior haríamos: java org.apache.axis.wsdl.Java2WSDL -o wp.wsdl l"http://localhost:8080/axis/services/MyWidgetPr ice" -n "urn:Example6" -p"ej5java2wsdl" "urn:Example6" ej5java2wsdl.MyWidgetPrice donde: -o indica el nombre del fichero WSDL de salida -l denota la localización del servicio -n es el espacio de nombres de destino del fichero WSDL -p indica un mapeo del paquete al espacio de nombres. la clase que contiene la interfaz del servicio web. Para más información sobre Java2WSDL revisar http://ws.apache.org/axis/java/reference.html Java2WSDL 3. Utilizar WSDL2Java para generar los bindings El comando: java org.apache.axis.wsdl.WSDL2Java -o . -d Session -s -S true -Nurn:Example6 ej5java2wsdl wp.wsdl Generaría: WidgetPriceSoapBindingImpl.java : fichero Java conteniendo la implementación por defecto de la parte servidora del servicio web Web Service Habrá que modificar esta clase para añadir tu implementación WidgetPrice.java: nueva interfaz que contiene los java.rmi.Remote apropiados WidgetPriceService.java: fichero que contiene la interfaz de la parte cliente WidgetPriceServiceLocator.java: fichero conteniendo la implementación de la parte cliente del servicio WidgetPriceSoapBindingSkeleton.java: el skeleton de la parte servidora WidgetPriceSoapBindingStub.java: el stub de la parte cliente deploy.wsdd: descriptor de explotación undeploy.wsdd: descriptor de desesplotación Tipos de datos: ficheros correspondientes a los tipos y holders del servicio web Servicios Web de Consumo Público Acceder a la url: http://www.xmethods.net Generar la parte cliente del servicio web con el comando WSDL2Java Tareas Ant para Construir Ejemplos Las siguientes tareas en Ant simplifican la compilación y despliegue de servicios web: <axis-wsdl2java> <axis-java2wsdl> <axis-admin> Para más información mirar en: http://ws.apache.org/~toshi/jp-site/axis/java/ant/ant.html Revisar ejemplo samples\userguide\example6\build.xml Cliente Calculadora en .NET Vamos a realizar un cliente para nuestro Servicio Web calculadora en .NET: wsdl http://localhost:8080/axis/Calculator.j ws?wsdl Escribimos fichero Calculadora.cs csc CalculatorService.cs Calculadora.cs Ejecutamos: Calculadora.exe Calculadora.cs using System; class Calculadora { public static void Main () { CalculatorService calc = new CalculatorService (); int sum = calc.add (2, 2); Console.WriteLine ("2 + 2 = " + sum); int resta = calc.subtract (2, 2); Console.WriteLine ("2 - 2 = " + resta); } } Cliente Calculadora en Java Pasos de desarrollo: 1. 2. 3. 4. java org.apache.axis.wsdl.WSDL2Java http://localhost:8080/axis/Calcu lator.jws?wsdl Escribir clase CalcClient Compilarla: javac CalcClient Ejecutarla: java CalcClient Cliente Calculadora en Java import localhost.axis.Calculator_jws.*; public class CalcClient { public static void main(String [] args) throws Exception { // Make a service CalculatorService service = new CalculatorServiceLocator(); // Now use the service to get a stub which implements the SDI. Calculator port = service.getCalculator(); // Make the actual call int sum = port.add(2,2); System.out.printf("2+2=%d\n", sum); int resta = port.subtract(2,2); System.out.printf("2-2=%d\n", resta); } }