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.
Características de Apache CXF
Las características principales de CXF son:
- Soporte para estándares de Servicios Web: CXF soporta varios estándares de servicios web incluyendo a SOAP, el Perfil Básico, WSDL, WS-Addressing, WS-Policy, WS-ReliableMessaging y WS-Security.
- Interfaces: CXF soporte varios modelos de programación como "interfaz". CXF implementa el API JAX-WS. También incluye una "interfaz simple" que permite crear clientes y endpoints sin utilizar anotaciones. CXF soporta el desarrollo por contrato primero con WSDL, y el desarrollo por código primero comenzando desde Java.
- Facilidad de uso: CXF está diseñado para ser intuitivo y facil de usar. Hay APIs simples para construir servicios comenzando por el código, plug-ins de Maven para integrar esta herramienta, soporte para el API JAX-WS, soporte de XML de Spring 2.0 para facilitar la configuración, y mucho más.
- Soporte para protocolos binarios y legacy: CXF fue diseñado para proveer una arquitectura extensible que no sólo soporte XML sino también otros binding no-XML, como JSON y CORBA, en combinación con cualquier tipo de transporte.
Construcción de un servicio web con Apache CXF
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!
Creando el servicio web
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:
- Crear la interfaz del servicio web, HolaMundo.java
- Crear la implementación del servicio web, HolaMundoImpl.java
- Crear el archivo de configuración de Spring, applicationContext.xml
- Configurar el archivo web.xml, en donde agregaremos el servlet de Apache CXF
1. Crear la interfaz del servicio web, HolaMundo.java
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 ... }
2. Crear la implementación del servicio web, HolaMundoImpl.java
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.
3. Crear la configuración de Spring
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:
- Importar algunos recursos de Apache CXF.
- Declarar como un bean la clase implementación.
- Declarar el servicio web con un tag propio de Apache CXF, en donde indicaremos la dirección desde donde será accesible.
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>
4. Configurar el archivo web.xml
Nos queda el último paso, que será configurar el archivo web.xml. Allí deberemos realizar dos acciones:
- Configurar el listener de Spring para que levante el factory (o cualquier otro mécanismo de Spring)
- Configurar el servlet de Apache CXF que se encargará de exponer el servicio web.
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.
Desplegando el servicio web
¡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.
Construcción de un cliente de servicios web con CXF
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:
- Crear el archivo de configuración de Spring, applicationTest.xml
- Crear un test JUnit para probar el cliente
1. Crear el archivo de configuración de Spring
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!
2. Crer un test JUnit para probar el cliente
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()); } }
Conclusión
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 ejemplo
Pueden 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.