Apache CXF es un framework de servicios de Software Libre. CXF nos ayuda a construir y desarrollar servicios utilizando JAX-WS como API de programación. Estos servicios pueden hablar una gran variedad de protocolos como SOAP, XML/HTTP, HTTP RESTful, o CORBA, y pueden trabajar sobre transportes como HTTP, JMS o JBI.
Las características principales de CXF son:
Para ejemplificar su uso vamos a construir un servicio web partiendo de código Java (con anotaciones JAX-WS). Luego usaremos Spring y CXF para crear el servicio web sobre Tomcat. Por último, crearemos un cliente para el servicio web usando CXF. ¡Manos a la obra!
Crearemos un servicio web "HolaMundo" que devuelva un saludo personalizado. Todas las clases las crearemos dentro de un módulo web (WAR), el cual desplegaremos en Tomcat. Los pasos a seguir serán los siguientes:
package com.dosideas.cxf; import javax.jws.WebParam; import javax.jws.WebResult; import javax.jws.WebService; @WebService public interface HolaMundo { String decirHola(String nombre); @WebResult(name="persona") Persona buscarPersona(@WebParam(name="legajo") long legajo); }
La anotación @WebService de JAX-WS indica que esta clase será tratada como un Servicio Web. Es la única anotación obligatoria en la interfaz para Apache CXF. Sin embargo, pueden usarse otras anotaciones (como @WebParam, @WebResult y más) para configurar más detalladamente el servicio web que se generará. En la interfaz usamos las anotaciones @WebParam y @WebResult para darle un nombre particular a los elementos del parámetro y del resultado. Si no los indicamos, se generarán con valores predeterminados.
La clase Persona es un simple POJO que representa un objeto de dominio:
package com.dosideas.cxf; public class Persona { private long legajo; private String nombre; //getter y setters a continuacion ... }
Creamos la implementación de nuestro servicio, que cumplirá con la interfaz HolaMundo.
package com.dosideas.cxf; import javax.jws.WebService; @WebService(endpointInterface = "com.dosideas.cxf.HolaMundo") public class HolaMundoImpl implements HolaMundo { public String decirHola(String nombre) { return "Hola, " + nombre; } public Persona buscarPersona(long legajo) { Persona persona = new Persona(); persona.setLegajo(legajo); persona.setNombre("Mock de persona para el legajo " + legajo); return persona; } }
La anotacion @WebService(endpointInterface = "com.dosideas.cxf.HolaMundo") en esta clase le indica a Apache CXF cuál será la interfaz de este servicio web. Es la única anotación que se necesita agregar en la implementación.
Apache CXF se integra totalmente con Spring, y hace que la configuración del servicio web sea muy sencillo. En un archivo de Spring deberemos:
Llamaremos applicationContext.xml a este archivo de configuración, el cual queda muy sencillo:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/ beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> <bean id="holaMundoImpl" class="com.dosideas.cxf.HolaMundoImpl"/> <jaxws:endpoint id="holaMundo" implementor="#holaMundoImpl" address="/HolaMundo" /> </beans>
Nos queda el último paso, que será configurar el archivo web.xml. Allí deberemos realizar dos acciones:
El archivo web.xml queda entonces:
<?xml version="1.0" encoding="UTF-8"?> <web-app> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class> org.apache.cxf.transport.servlet.CXFServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>30</session-timeout> </session-config> </web-app>
El servlet CXFServlet de Apache CXF se encarga de recibir todas las peticiones a la aplicación web. Cuando accedamos a la raiz de nuestra aplicación web veremos un listado con todos los servicios web del módulo.
¡Ya casi está todo listo! Nos queda empaquetar todos estos archivos dentro del módulo web (wAR) y desplegarlo en nuestro contenedor Web. Si usamos Tomcat o GlassFish (u otros "clásicos") podremos desplegar la aplicación sin más cambios. Para otros contenedores deberemos consultar la guía de configuración específica para servidores de aplicaciones (en general es cuestión de agregar configuración específica para cada servidor de aplicaciones).
Suponiendo que hayamos desplegado la aplicacion web en un Tomcat en el puerto 8084 bajo el contexto "cxf-demo" podemos abrir nuestro navegador preferido (Firefox, o sea) y escribir:
http://localhost:8084/cxf-demo
Veremos un listado con nuestro servicio web, sus dos operaciones y la URL del WSDL. ¡Mágico! A continuación veremos cómo crear un cliente de servicios web.
La creación de clientes de servicios web con Apache CXF es muy sencilla, y se integra completamente con Spring.
Usando tags propios de CXF, podremos configurar el cliente como un bean más, e inyectarlo en cualquier parte de nuestra aplicación.
Deberemos contar con una interfaz Java que cumpla con la firma del servicio web. En este ejemplo, usaremos la misma clase HolaMundo.java como interfaz, pero podría ser otra interfaz (siempre y cuando cumpla con la firma).
A continuación entonces realizaremos dos pasos:
Lo primero será crear un archivo de configuración de Spring, que llamaremos applicationTest.xml, con un único bean que representa al cliente de nuestro servicio web. Apache CXF se encargará de realizar la conexión al servicio web, serializar y deserializar los datos y más.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/ beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <!-- Este bean será el cliente del Web Service. Apache CXF generará un cliente que cumpla con la interfaz indicada y que accede al Web Service indicado en el atributo "address". Este bean luego puede inyectarse y utilizarse normalmente como cualquier otro objeto. --> <jaxws:client id="holaMundoCliente" serviceClass="com.dosideas.cxf.HolaMundo" address="http://localhost:8084/HolaMundo" /> </beans>
Como vemos, tenemos un bean holaMundoCliente el cual representa el servicio web. ¡Más facil imposible!
Por último, crearemos un test JUnit para comprobar el correcto funcionamiento de nuestro cliente. Por supuesto, para ejecutar este test JUnit deberemos tener desplegado el servicio web que hicimos anteriormente.
package com.dosideas.cxf; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.junit.Assert.*; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"classpath:com/dosideas/cxf/applicationTest.xml"}) public class ClienteHolaMundoTest { @Autowired private HolaMundo instance; @Test public void testDecirHola() { System.out.println("decirHola"); String nombre = "Zim"; String expResult = "Hola, " + nombre; String result = instance.decirHola(nombre); assertEquals(expResult, result); } @Test public void testBuscarPersona() { System.out.println("buscarPersona"); long legajo = 29L; Persona result = instance.buscarPersona(legajo); assertNotNull(result); assertEquals(legajo, result.getLegajo()); assertNotNull(result.getNombre()); assertTrue(!result.getNombre().isEmpty()); } }
Apache CXF es un framework Java para la utilización de servicios web. Cuenta con una fuerte integración con Spring, por lo que es muy conveniente de facil de configurar para proyectos que usen este framework de aplicación.
Apache CXF es muy flexible y cuenta con muchísimas opciones para crear servicios web, partiendo desde código Java (como acabamos de ver), o desde un WSDL ya existente.
Para aprender más sobre Apache CXF pueden descargar este ejemplo a continuación, y leer la documentación de Apache CXF.
Descargar el proyecto de ejemploPueden descargar el proyecto de ejemplo de Apache CXF, un proyecto de NetBeans IDE 6.5 ya configurado y con todas las librerías necesarias para compilar y ejecutar esta demo.