mundo-con-procesamientoApache 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:

  1. Crear la interfaz del servicio web, HolaMundo.java
  2. Crear la implementación del servicio web, HolaMundoImpl.java
  3. Crear el archivo de configuración de Spring, applicationContext.xml
  4. 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:

  1. Importar algunos recursos de Apache CXF.
  2. Declarar como un bean la clase implementación.
  3. 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:

  1. Configurar el listener de Spring para que levante el factory (o cualquier otro mécanismo de Spring)
  2. 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:

  1. Crear el archivo de configuración de Spring, applicationTest.xml
  2. 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 proyectoDescargar 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.

Inspiración.

"Si tú tienes una manzana y yo tengo una manzana e intercambiamos las manzanas, entonces tanto tú como yo seguiremos teniendo una manzana cada uno. Pero si tú tienes una idea y yo tengo una idea, e intercambiamos las ideas, entonces ambos tendremos dos ideas"

Bernard Shaw