martes, 16 de octubre de 2012

CXF utilizando JAX-WS integrado con Spring

Apache CXF es un framework de servicios de Software Libre. CXF nos ayuda a construir y desarrollar servicios utilizando JAX-WS.

CXF soporta 3 tipos de servicios:

1. SOAP
2. REST-ful - REST support
3. CORBA

Un tutorial que explica paso a paso:

http://www.dosideas.com/noticias/java/396-servicios-web-con-apache-cxf.html


IMPORTANTE - Para el Cliente que consumirá el WS:

Lo que se tiene que tener en cuenta es que cuando se realice el cliente, vamos a tener que generar la interfaces con todos los objetos resultantes de las respuesta y parámetros de entrada de los métodos para comunicarnos con los WS.
Dichas interfaces no pueden estar sin las anotaciones (@WebService) que determinan como hacer el binding, por mas que se haya configurado en el applicationContext.xml de la siguiente manera:

 <jaxws:client id="helloClient"
                  serviceClass="demo.spring.HelloWorld"
                  address="http://localhost:9002/HelloWorld" />




Es decir, con la anotación @WebService alcanzo para que funcione pero no estamos seguro si es la manera correcta de hacerlo.

Para no tener problemas lo mejor es generar las clases cliente (que luego vamos a utilizar en la aplicacion que va a consumir el WS) es utilizar la herramienta de CXF (http://cxf.apache.org/download.html) mediante el comando wsdl2Java (http://cxf.apache.org/docs/wsdl-to-java.html):

wsdl2java http://localhost:8080/SpringCXFProject/HelloWS?wsdl

o bien:

wsdl2java -p spring.ejemplos.diecisiete.ws.cxf.client.cxfgeneratedcode http://localhost:8080/SpringCXFProject/HelloWS?wsdl

Otra forma de generar los clientes es directamente con JAVA 6 utilizando wsimport:

wsimport -p spring.ejemplos.diecisiete.ws.cxf.client.jaxwsgeneratedcode -keep http://localhost:8080/SpringCXFProject/HelloWS?wsdl

Ver esta pagina en la parte del cliente que ahi nos indica como generar las clases clientes

http://blog.jeshurun.ca/technology/jax-ws-web-services-with-spring-and-cxf

En cualquier caso, como estamos haciendo un cliente de WS con Spring integrado con CXF, y en el appContext.xml como tenemos un tag propio de CXF llamado <jaxws:client.... es que vamos a tener que agregar en el POM las dos dependencias de CXF también en el cliente (las mismas que tenemos en el WS):


<!-- Dependencias de CXF http://cxf.apache.org/docs/using-cxf-with-maven.htm -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.2.3</version>
</dependency>

<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.2.3</version>
</dependency>


RESUMEN:

Para poder consumir el WS utilizando Sproing integrado con CXF, tenemos 3 alternativas:

1. Generar el cliente a mano utilizando una interface pelada solo con la anotacion WebService
2. Generar el cliente utilizando la herramienta CXF wsdl2java
2. Generar el cliente utiilizando la JDK6 wsimport

Las dependencias de CXF para maven las sacamos de aqui (ojo que estas dependencias van tanto en el proyecto de WS en si como en el cliente que consumira dicho WS):

http://cxf.apache.org/docs/using-cxf-with-maven.html

El codigo de este ejemplo lo podemos encontrar aqui:

http://gwt-spring-hibernate-maven.googlecode.com/svn/trunk/SpringProject/src/main/java/spring/ejemplos/diecisiete/ws/cxf/client/

Para leer un poco mas...
http://unpocodejava.wordpress.com/2010/03/30/web-services-con-cxf/
http://cxf.apache.org/docs/writing-a-service-with-spring.html

Al integrar el WS con con Spring, permite la publicación de beans de Spring como Web Services

Otro código de ejemplo se lo puede encontrar aquí:

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





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

viernes, 12 de octubre de 2012

Eclipse y Tomcat

Una opción es instalar el plugin JBoss Tool, pero este plugin para el eclipse Indigo  no trea el adaptador para el servidor tomcat.

Y para el adaptador del Tomcat necesitamos el JST server adapter.

JST server adapter y JST server adapter extensions - Esto instala
http://stackoverflow.com/questions/5066088/eclipse-wtp-plugin-no-apache-tomcat-adapter
http://codeissue.com/issues/i84f32f12843884/tomcat-web-server-plugin-for-eclipse

1. Go to Help > Install New Software...
2. From the Work With, select "Indigo - http://download.eclipse.org/releases/indigo"
3. From the list, select "Web, XML, and Java EE Development"
4. Then select "JST Server Adapters

Para Eclipse LUNA:

1. Go to Help/Install new Software
2. Choose "Luna - http://download.eclipse.org/releases/luna"
3. Check "JST Server Adapters" and "JST Server Adapters Extensions"
4. Check "m2e-wtp Maven integration for wtp"
5. Once installed, go to "Window/Preferences/Server/Runtime Environments" and you'll find Apache Tomcat servers
Como alternativa para un HTTP servecer podemos bajarnos un subset del WTP llamado WST que trae los adaptadores clasicos HTTP.

O bien otra alternativa es instalar el plugin conocido como WTP: para lo cual debemos ingresar la siguiente URL: http://download.eclipse.org/webtools/repository/luna/
Ver> https://www.mulesoft.com/tcat/tomcat-wtp#wtp

WST adapter - Esto instalal  dos adaptadores HTTP Server:
https://yoxos.eclipsesource.com/yoxos/node/org.eclipse.wst.server_adapters.feature.feature.group