lunes, 15 de octubre de 2012

JAX-WS & JAX-RPC - Web Services

JAX-WS 2.0 es la especificación actual de Java para desarrollar web services mediante anotaciones. JAX-WS forma parte del estándar Java EE, conocido antes como J2EE (el cual incluye varias especificaciones de API, tales como JDBC, RMI, e-mail, JMS, Servicios Web, XML, etc)

En la plataforma Java EE, JAX-RPC 2.0 (Java API for XML Based RPC) fue renombrada a JAX-WS 2.0 (Java API for XML Web Services). Este cambio en el nombre demuestra el cambio de estilo de RPC a Documento

JAX-RPC forget about this one. It is the old obsolete standard for Java Web Services

JAX-WS new standard for SOAP-Based web services (also is provided as a reference implementation)

JAX-RS stack for REST-full web services

Ver: http://finallyigotit.blogspot.com/2009/05/jax-rpc-vs-jax-ws.html

La interface de un Web Service es especificada por el WSDL. El WSDL es un XML que contiene toda la informacion para que el WS sea localizado y pueda ser accedido.

La implementacion de un servicio SOA generalmente es un WS, pero puede no serlo. Por ejemplo, un servicio de mensajería JMS puede ser tranquilamente otra forma de implementar un servicio

Todo servidor de aplicaciones compatible con Java EE 5 implementa una API para web service llamada: JAX-WS la cual define el mapeo entre java y el WSDL. El mapeo entre los objetos Java y el WSDL ( que es un XML ) lo delega en el API JAXB 2.0.

Existen dos maneras de crear los WS

Crear el WSDL y luego, basándonos en el WSDL, creamos el WS (la clase java conocida como endpoint)
Crear la clase java (endpoint) y luego generamos su correspondiente WSDL.

Existen varias implmementaciones para desarrollar WS en Java (algunas de las mas conocidas son):

Axis (http://axis.apache.org/axis/): Soporta JAX-RPC API
Axis2 (http://axis.apache.org/axis2/java/core/): Soporta JAX-WS API
Apache CFX (http://cxf.apache.org/): Soporta JAX-WS API
JBossWS (http://www.jboss.org/jbossws):Soporta JAX-WS API

Como podemos ver, todos estos SOAP engines (implementaciones) menos Axis no están dentro del estándar JAX-WS.

Como para que nos quede un poco mas claro, JAX-WS es para Apache CXF lo que JPA es para Hibernate.

IMPORTANTE:

Si no se quiere utilizar ninguna implementacion existente, la JDK trae su propia implementacion para desarrollar WS en Java (en este caso no vamos a utilizar ninguno de los engines descriptos anteriormente como por ejemplo CXF):


RESTful services (Mostly web integration, mobile phone apps)
  • Integration over web will be easy with the REST. Popularly used with the AJAX calls.
  • Not verbose as SOAP services so need less bandwidth hence good to use for the mobile apps.
  • Web services are completely stateless so only for stateless services.

JAX-WS and JAX-RPC are SOAP based services. (Enterprise web services)
  • JAX-WS JEE later versions support this and standards still evolving. 
  • SOAP based services not preferred for mobile app communication because of heavy payload compare to rest
  • More suitable for the enterprise web services where you need interoperability, transactions, message delivery and reliability.
http://www.javamexico.org/blogs/mariogarcia/servicios_web_con_apache_cxf_utilizando_jaxws_y_jaxrs

Creando un WS con JAX-WS

Paso a paso como crear un WS utilizando el API JAX-WS (http://es.wikipedia.org/wiki/JAX-WS)

http://maksim.sorokin.dk/it/2011/01/20/jax-ws-web-services-maven-tomcat/
http://www.mkyong.com/webservices/jax-ws/deploy-jax-ws-web-services-on-tomcat/

Y para consumirlo a modo de prueba podemos utilizar la SOAP UI

http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=introduccion-soapUI


Creando un cliente de WS

Para esto utilizamos el comando

wsimport -p nombrepaquete -keep http://localhost:8080/WSProject/HelloWS?wsdl

El cual generará los .java correspondientes para poder acceder al WS creado previamente.

http://ccia.ei.uvigo.es/docencia/SCS/practicas0809/practica-6/index.html
http://www.mkyong.com/webservices/jax-ws/jax-ws-wsimport-tool-example/

En esta pagina podemos ver varios parámetros que podemos pesarle al comando wsimport

http://amalaka.wordpress.com/2010/02/25/111/

El codigo fuente se lo puede encontrar aqui

https://gwt-spring-hibernate-maven.googlecode.com/svn/trunk/WSProject

IMPORTANTE:

Muchas veces vamos a tener que sobreescribir el endpoint desde el cliente para poder acceder al WS. Para esto hay dos opciones:

http://stackoverflow.com/questions/2490737/how-to-change-webservice-url-endpoint

Opcion 1:
EchoService service = new EchoService();
Echo port = service.getEchoPort();

/* Set NEW Endpoint Location */
String endpointURL = "http://NEW_ENDPOINT_URL";
BindingProvider bp = (BindingProvider)port;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);

System.out.println("Server said: " + echo.echo(args[0]));
Opcion 2:
...
URL newEndpoint = new URL("NEW_ENDPOINT_URL");
QName qname = new QName("http://ws.mycompany.tld","EchoService"); 

EchoService service = new EchoService(newEndpoint, qname);
Echo port = service.getEchoPort();

System.out.println("Server said: " + echo.echo(args[0]));
...



Creando un WS con JAX-RPC 

AXIS en su primera versión implementaba JAX-RPC y proveía un contenedor relativamente versátil para su epoca de lanzamiento y sobre todo de propagación (entre 2004 y 2007).

Vamos a descargar AXIS 1.4 y copiar dentro de la carpeta WEBAPPS del TOMCAT la carpeta AXIS que se encuentra dentro de la carpeta WEBAPPs de proyecto AXIS


GENERACION WSDL:


java -cp e:\axis_libs\axis-ant.jar;e:\axis_libs\axis.jar;e:\axis_libs\commons-discovery-0.2.jar;e:\axis_libs\commons-logging-1.0.4.jar;e:\axis_libs\jaxrpc.jar;e:\axis_libs\log4j-1.2.8.jar;e:\axis_libs\saaj.jar;e:\axis_libs\wsdl4j-1.5.1.jar;e:\axis_libs org.apache.axis.wsdl.Java2WSDL -o Calculator.wsdl -n urn:org.axis.ws -l http://localhost:8080/axis/services/calculator org.axis.ws.Calculator

GENERACION CLASES SERVER SIDE Y CLIENT SIDE

java -cp e:\axis_libs\axis-ant.jar;e:\axis_libs\axis.jar;e:\axis_libs\commons-discovery-0.2.jar;e:\axis_libs\commons-logging-1.0.4.jar;e:\axis_libs\jaxrpc.jar;e:\axis_libs\log4j-1.2.8.jar;e:\axis_libs\saaj.jar;e:\axis_libs\wsdl4j-1.5.1.jar;e:\axis_libs org.apache.axis.wsdl.WSDL2Java -o e:\axis_libs\src -p org.axis.ws.generated -s calculator.wsdl

NOTA: Para ambos casos necesitaremos tener los JARs de la carpeta LIB que nos viene con AXIS cuando lo descargamos

Para esto vamos a necesitar las siguientes dos clases que podemos ver en cualquier tutorial de AXIS


package org.axis.ws;

public interface Calculator {
    int add (int x, int y);
    int subtract(int x, int y);
}


package org.axis.ws;

public class CalculatorImpl {
    public int add(int a, int b) {
        return a + b;
    }
    public int subtract(int a, int b) {
        return a - b;
    }
    public int multiply(int a, int b) {
        return a * b;
    }
}

Y con los camandos anteriores nos va a generar los siguientes archivos:



Otra forma de generar el cliente mediante el WSDL

http://www.devx.com/tips/Tip/37414

En esta pagina muestra de una manera muy simple como hacerlo en dos pasos:

1. Armamos una carpeta con los libs del AXIS, ej e:\cliente_prueba y ahi tiramos todos los libs

2. E:\cliente_prueba>set classpath=%CLASSPATH%;axis.jar;axis-ant.jar;commons-discovery-0.2.jar;commons-logging-1.0.4.jar;jaxrpc.jar;log4j-1.2.8.jar;saaj.jar;wsdl4j-1.5.1.jar;e:\cliente_prueba

3. E:\cliente_prueba>java org.apache.axis.wsdl.WSDL2Java prueba.wsdl

Dependencias para Maven para consumirlo:

<!-- AXIS dependency  -->

<dependency>
<groupId>axis</groupId>
<artifactId>axis-jaxrpc</artifactId>
<version>1.4</version>
</dependency>

<dependency>
<groupId>org.apache.axis</groupId>
<artifactId>axis</artifactId>
<version>1.4</version>
</dependency>

<dependency>
<groupId>commons-discovery</groupId>
<artifactId>commons-discovery</artifactId>
<version>0.2</version>
</dependency>

<dependency>
<groupId>axis</groupId>
<artifactId>axis-wsdl4j</artifactId>
<version>1.5.1</version>
</dependency>

<dependency>
<groupId>axis</groupId>
<artifactId>axis-saaj</artifactId>
<version>1.4</version>
</dependency>

Otra forma de generar el cliente y el server


NOTA: agregamos la "-S" de esta manera nos generara el deploy.wsdd y undeploy.wsdd para registrar el WS.

1. Armamos una carpeta con los libs del AXIS, ej e:\cliente_prueba y ahi tiramos todos los libs

2. E:\cliente_prueba>set classpath=%CLASSPATH%;axis.jar;axis-ant.jar;commons-discovery-0.2.jar;commons-logging-1.0.4.jar;jaxrpc.jar;log4j-1.2.8.jar;saaj.jar;wsdl4j-1.5.1.jar;e:\cliente_prueba

3 E:\cliente_prueba>java org.apache.axis.wsdl.WSDL2Java -s prueba.wsdl

IMPORTANTE - SERVER-CONFIG:WSDD:

Para que nuestro servicio web se despliegue automáticamente cuando hagamos el despliegue del WAR en nuestro servidor de aplicaciones, deberemos crear un archivo llamado server-config-wsdd dentro de la carpeta /WEB-INF. Este archivo indicará al servidor de aplicaciones que clases definen un WS y como están configuradas. Además será donde se pueda integrar cualquier tipo de configuración y manejadores (handlers) para los WS.

La parte que engloba la etiqueta service del archivo wsdd es lo que importa. Lo demás es fijo para todos los WS que hagamos. Si queremos desplegar más de un WS en un mismo WAR, debemos añadir más etiquetas service a nuestro descriptor server-config.wsdd.

Algunos tips:

o – output folder -> src
p – package for generated classes -> org.kamal.wssample.ws.generated
s – generate server side classes as well
Por ejemplo, podemos ver alguna de las clases generadas por AXIS:


/**
 * Calculator.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */

package org.axis.ws.generated;

public interface Calculator extends java.rmi.Remote {

    public int add(int in0, int in1) throws java.rmi.RemoteException;
    public int subtract(int in0, int in1) throws 
java.rmi.RemoteException;

}

/**
 * CalculatorService.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */

package org.axis.ws.generated;

public interface CalculatorService extends javax.xml.rpc.Service {

    public java.lang.String getcalculatorAddress();

    public org.axis.ws.generated.Calculator getcalculator() throws javax.xml.rpc.ServiceException;

    public org.axis.ws.generated.Calculator getcalculator(java.net.URL portAddress) throws javax.xml.rpc.ServiceException;
}


Y genera también dos archivos deploy.wsdd y undeploy.wsdd que contienen información que le sirve a Apache Axis para hacer un deploy/undeploy de nuestro servicio en el servidor de aplicaciones.

Luego vamos a tener que copiar los archivos generados anteriormente (todos,  tanto los generados con los comnados de axis como las clases iniciales compiladas) a la carpeta CLASS del proyecto AXIS.

IMPORTANTE: Vamos a tener que compilarlos a todos (una opción es meterlo en el proyecto nuestro y compilarlo con mvn clean package). Una vez que tengamos todos los .class recién ahi los copiamos a la carpeta CLASS del proyecto AXIS del tomcat




Luego, vamos a registrar el WS en AXIS mediante el siguiente comando utilizando el archivo deploy.wsdd:

NOTA: para esto necesitamos tener levantado el TOMCAT.

java -cp e:\axis_libs\axis-ant.jar;e:\axis_libs\axis.jar;e:\axis_libs\commons-discovery-0.2.jar;e:\axis_libs\commons-logging-1.0.4.jar;e:\axis_libs\jaxrpc.jar;e:\axis_libs\log4j-1.2.8.jar;e:\axis_libs\saaj.jar;e:\axis_libs\wsdl4j-1.5.1.jar;e:\axis_libs org.apache.axis.client.AdminClient  e:\axis_libs\src\org\axis\ws\generated\deploy.wsdd



This command will deploy the web service into axis. Now restart (Tomcat) server.

To verify our web service is deployed correctly; try following url from your browser.

http://localhost:8080/axis/services/calculator?wsdl

(change the port 8080 in url to match the port on your machine)





Ver: http://www.digizol.com/2008/07/web-service-axis-tutorial-client-server.html

No hay comentarios:

Publicar un comentario