2010-11-18 20 views
5

Me gustaría escribir un interceptor para la implementación Apache CXF JAX-RS que inspecciona el servicio/método objetivo para una anotación particular y realiza algún procesamiento especial para esa anotación.Determine el servicio/método objetivo de CXF Interceptor

Parece que no puedo encontrar nada en la documentación del interceptor que describa cómo hacerlo. ¿Alguien tiene alguna idea?

Gracias!

Respuesta

4

Ah. No especifiqué que estaba usando la parte JAX-RS de CXF; no estoy seguro si eso impacta la respuesta de Daniel Kulp pero su solución en realidad no funcionó para mí. Creo que es porque CXF hace las cosas de manera diferente cuando se maneja JAX-RS.

me encontré con la fuente de CXF de [JAXRSInInterceptor][1] y vi en ese código que este interceptor está poniendo la información método en el objeto Exchange así:

message.getExchange().put(OperationResourceInfo.class, ori);

... durante la fase de UNMARSHAL, que según el CXF interceptor docs ocurre antes de la fase *_LOGICAL. Así escribiendo un Interceptor que se encarga de la fase USER_LOGICAL que puedo hacer:

message.getExchange().get(OperationResourceInfo.class)

... para acceder allí a la Method y Class<?> del Service manejar la llamada!

+0

¡Esto arrojará resultados incorrectos si está utilizando sub-recursos! El ORI devuelto será el utilizado para seleccionar el método de localización de recursos secundarios, pero no el método del controlador acutal –

+1

Funciona perfectamente, si necesita el nombre del método solo use 'operationResInfo.getMethodToInvoke(). GetName();' –

+0

Y si necesita la clase use 'operationResInfo.getMethodToInvoke(). getDeclaringClass()' – fafl

8

Si el interceptor funciona bastante tarde en la cadena (como la fase USER_LOGICAL ), usted debe ser capaz de hacer algo como:


Exchange exchange = msg.getExchange(); 
BindingOperationInfo bop = exchange.get(BindingOperationInfo.class); 
MethodDispatcher md = (MethodDispatcher) 
       exchange.get(Service.class).get(MethodDispatcher.class.getName()); 
Method meth = md.getMethod(bop); 

que debe darle el método que fue atado en lo que puede obtener la clase declarada o las anotaciones, etc ...

+0

Aha, ese es el tipo de cosas que estaba buscando, pero supongo que no sabía la terminología de CXF a atraviesa las clases. :) Voy a dar un tiro, gracias! –

+1

MethodDispatched está en desuso. ¿Puedes sugerir alguna otra alternativa? Estoy usando PRE_STREAM & RECEIVE fases – Harish

1

Es bastante en algún momento desde la respuesta aceptada. Pero hay pocas abstracciones de apoyo previstas en el

cxf-rt-core-2.7.3.jar 

Uno en que se org.apache.cxf.interceptor.security.AbstractAuthorizingInInterceptor

extracto de la muestra de la fuente podría ser una buena referencia.

protected Method getTargetMethod(Message m) { 
    BindingOperationInfo bop = m.getExchange().get(BindingOperationInfo.class); 
    if (bop != null) { 
     MethodDispatcher md = (MethodDispatcher) 
      m.getExchange().get(Service.class).get(MethodDispatcher.class.getName()); 
     return md.getMethod(bop); 
    } 
    Method method = (Method)m.get("org.apache.cxf.resource.method"); 
    if (method != null) { 
     return method; 
    } 
    throw new AccessDeniedException("Method is not available : Unauthorized"); 
} 
0

La construcción de la respuesta del interrogador original, me ocurrió con esta

public UserContextInterceptor() { 
    super(Phase.USER_LOGICAL); 
} 

@Override 
public void handleMessage(Message message) { 
    if(StringUtils.isEmpty(getHeader("some-header-name", message))) { 
     final Method method = getTargetMethod(message); 
     if(isAnnotated(method.getDeclaringClass().getAnnotations()) || isAnnotated(method.getAnnotations())) { 
      final Fault fault = new Fault(new LoginException("Missing user id")); 
      fault.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED); 
      throw fault; 
     } 
    } 
} 

private static Method getTargetMethod(Message message) { 
    final Exchange exchange = message.getExchange(); 
    final OperationResourceInfo resource = exchange.get(OperationResourceInfo.class); 
    if(resource == null || resource.getMethodToInvoke() == null) { 
     throw new AccessDeniedException("Method is not available"); 
    } 
    return resource.getMethodToInvoke(); 
} 

private static boolean isAnnotated(Annotation[] annotations) { 
    for(Annotation annotation : annotations) { 
     if(UserRequired.class.equals(annotation.annotationType())) { 
      return true; 
     } 
    } 
    return false; 
} 
Cuestiones relacionadas