Filtros e Interceptores de CXF (Rest)

En el contexto de las aplicaciones web, y en concreto de servicios REST, algunas veces parte del flujo de negocio, como puede ser la seguridad, nos planteamos controlarlo con un filtro o un interceptor.
Muchas de las cosas se pueden controlar igual con unos y con otros. Y la discusiones dentro de los equipos de trabajo sobre la opción más correcta a emplear se termina por dilucidar por lo primero que alguien consigue que le funcione que suele ser directamente proporcional a la suerte que se tenga realizando búsquedas en google.
El proyecto completo se puede descargar completo al final pongo el enlace. Esencialmente es un proyecto con spring data, y cxf que, como prueba de concepto, ataca una bbdd embebida. El entorno de desarrollo es el habitual de los últimos proyectos jdk1.8, eclipse mars, spring 4.1.8.RELEASE, cxf 3.1.1.
El montón de perrerías que se pueden hacer con los interceptores y los fltros es inmenso y voy a tratar uno muy habitual  resolviendo un problema habitual de las dos maneras. ( Edito: en la siguiente entrada del blog abordo una tercera manera)
El problema a resolver es de acceso por llamadas ajax a un servicio rest : CORS la solución pasa por devolver en las cabeceras algo como
  • Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS, DELETE
  • Access-Control-Allow-Origin: *
  • La primera opción es utilizar un "Filter" que si estamos en una aplicación web clásica se configura en el descriptor de despligue, web.xml:
      <filter>
            <filter-name>corsfilter</filter-name>
            <filter-class>es.sinjava.data.CorsServletFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>corsfilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    El código de cualquier filtro es similar al siguiente:



    Posiblemente esa sea la forma más rápida y simple de solucionar el problema de CORS y de capturar una petición entrante/saliente. No creo que merezca la pena aclarar qué hace ese código, es trivial la interpretación.
    Si estamos en el contexto de servicios Rest y con Spring+CXF hay una forma que me parece mucho más elegante y potente utilizando interceptores, de entrada o de salida.
    Los interceptores pueden estar dentro o fuera del contexto de Spring, según nos interese. En mi opinión se tiende a abusar de meter cosas en el contexto innecesariamente.
    En este proyecto no utilizo Spring-boot pero si Spring con una clase de configuración:



    Esencialmente creo un datasource con una bbdd embebida, en la que cargo unos datos y configuro cada uno de los servicios. El método jaxRsServer funciona como un "autodiscover" de servicios buscando beans anotados con "@Path", luego algo de configuración genérica y luego los arrays de interceptores de entrada (InInterceptors) y de salida (OutInterceptors).
    En el ejemplo, el InInterceptor está en el contexto de Spring y el OutInterceptor está fuera.
    El OutInterceptor:


    Dicho interceptor hace lo mismo que el filtro antes comentado, obviamente un interceptor también puede hacer otras muchas cosas.
    InInterceptor:

    En este caso el interceptor de entrada captura alguna información de la petición, como la url a la que se llama, los parámetros de la query o parámetros de la cabecera.
    En este caso concreto no se debería haber metido en el contexto de Spring el interceptor de entrada para la parte del negocio que realiza, pero es una prueba de concepto.
    El proyecto completo puedes descargarlo aquí 

    Comentarios