Hemos creado algunos servicios web REST (jax-rs) utilizando Apache CXF. Devuelven una respuesta JSON.

Ahora necesito modificar algunos de los parámetros de la solicitud y el contenido de la respuesta. (Básicamente, necesitamos codificar / cifrar algunos de los datos que devuelve el servicio; y decodificar / descifrar los mismos datos cuando se utilizan como parámetro en una llamada de servicio posterior).

Parece que tengo al menos 4 opciones aquí:

  1. Utilice un filtro de servlet
  2. Utilice un interceptor CXF
  3. Utilice un filtro JAX-RS
  4. No utilice ningún patrón en particular y realice la codificación / decodificación dentro de la lógica de servicio real.

He usado filtros de servlet antes y entiendo exactamente cómo modificar los parámetros de solicitud y el cuerpo de respuesta, así que me inclino por eso. Sin embargo, estoy dispuesto a usar un interceptor CXF o un filtro JAX-RS si esa es la forma más 'correcta' de resolver esto al usar CXF. Pero según la documentación, realmente no entiendo cómo hacer esto. Por ejemplo, ¿utilizo el método setContent del objeto Message para cambiar la respuesta JSON? ¿Cuál es el parámetro de formato en ese caso, solo String.class?

11
Michael Lucas 7 feb. 2012 a las 19:52

1 respuesta

La mejor respuesta

Respondiendo a mi propia pregunta aquí ... Terminé usando un filtro JAX-RS, y funcionó bien, una vez que superé la falta de documentación. Usé la documentación (bastante escasa) de http://cxf.apache.org/ docs / jax-rs-filters.html. Tenga en cuenta que a pesar de su nombre, un filtro JAX-RS es una bestia específica de CXF, no parte del estándar JAX-RS (por lo que puedo decir).

Aquí hay un código de ejemplo:

@Context
private HttpServletRequest httpRequest;
@Context
private UriInfo uriInfo;

/**
 * @see org.apache.cxf.jaxrs.ext.ResponseHandler#handleResponse(org.apache.cxf.message.Message, org.apache.cxf.jaxrs.model.OperationResourceInfo, javax.ws.rs.core.Response)
 */
public Response handleResponse(Message message, OperationResourceInfo opResourceInfo, Response response) {
    try {

        // log the injected context data; useful for debugging CXF problems
        logContextData(httpRequest, uriInfo);

        OutputStream os = message.getContent(OutputStream.class);
        String relevantData = getDataFromRequest(httpRequest);
        message.setContent(OutputStream.class, new MyOutputStreamWrapper(os, relevantData));

    } catch (CustomException e) {
            // return some status that is related to CustomException
        return Response.status(Status.UNAUTHORIZED).build();
    } catch (Exception e) {
        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
    }

    return response;
}

/**
 * @see org.apache.cxf.jaxrs.ext.RequestHandler#handleRequest(org.apache.cxf.message.Message, org.apache.cxf.jaxrs.model.ClassResourceInfo)
 */
public Response handleRequest(Message message, ClassResourceInfo classResourceInfo) {
    try {

        // log the injected context data; useful for debugging CXF problems
        logContextData();

        String updatedQueryString = buildNewQueryString(this.uriInfo, httpRequest);

        message.put(Message.QUERY_STRING, updatedQueryString);


        // returning null tells CXF to continue the request (i.e. a non-null value would halt the request)
        return null;

    } catch (CustomException e) {
        // return some status that is related to CustomException
        return Response.status(Status.UNAUTHORIZED).build();
    } catch (Exception e) {
        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
    }
}

Debo señalar que la implementación de MyOutputStreamWrapper es la parte importante en la modificación del contenido de la respuesta. No pude incluir esa fuente aquí (de hecho, mi implementación tiene un nombre diferente) debido a consideraciones de seguridad.

9
Michael Lucas 11 oct. 2012 a las 01:24
2
Sería bueno si pudiera explicar la razón detrás de hacer su elección.
 – 
andthereitgoes
30 nov. 2012 a las 18:02
Tengo la misma pregunta, si CXF ha proporcionado un interceptor, ¿por qué todavía es necesario tener el filtro?
 – 
Chailie
19 dic. 2013 a las 11:43
3
- No había una razón sólida para optar por el filtro JAX-RS sobre el interceptor CXF, creo que la razón principal por la que lo elegí fue que era específico de JAX-RS, pero un interceptor CXF también habría funcionado. (Sin embargo, todavía habría requerido la misma cantidad de codificación personalizada). Tenga en cuenta que JAX-RS 2.0 ya está disponible, por lo que los filtros e interceptores JAX-RS se han convertido en parte de la especificación y definitivamente serían el camino a seguir con la tecnología actual .
 – 
Michael Lucas
2 ene. 2014 a las 18:51
Ver comentario anterior; tenga en cuenta que descarté la opción 4 porque realmente prefería una solución de tipo interceptor / filtro (separación de preocupaciones). Además, la opción 1 no era muy específica para el entorno CXF en el que estábamos.
 – 
Michael Lucas
2 ene. 2014 a las 18:53
Tenga en cuenta que con CXF 3.0.0 RequestHandler y ResponseHandler se han eliminado a favor de las clases JAX-RS 2.0 ContainerRequestFilter y ContainerResponseFilter (consulte CXF-4882)
 – 
dpr
29 ene. 2020 a las 15:35