2012-04-17 25 views
9

Estoy trabajando en alguna aplicación basada en servicios web y tengo una pregunta sobre el desajuste de Apache CXF. En nuestro proyecto utilizamos la versión CXF 2.4.1.Sobrescribir la gestión de errores CXF

Cuando alguna solicitud SOAP es incorrecta (por ejemplo, algún campo es texto en lugar de numérica) CXF lanza SOAPFaultException estándar y respuesta SOAP se construye con los campos estándar como:

<soap:Fault> 
    <faultcode>soap:Client</faultcode> 
    <faultstring>Unmarshalling Error: some field missing</faultstring> 
</soap:Fault> 

requisitos del proyecto dice que en caso de cualquier sistema de fallas tiene que responder en otro formato, como:

<soap:body> 
    <ResponseState> 
     <ErrorCode>2732</ErrorCode> 
     <ErrorMessage>Unmarshalling Error: some field missing</ErrorMessage> 
     <ErrorDetails> some details </ErrorDetails> 
     <some other fields> 
     ... 
    </ResponseState> 
</soap:body> 

Entonces la pregunta es: ¿cómo puedo anular de alguna manera esta gestión de errores y responder en mi formato, no por defecto?

Gracias de antemano.

P.S. Traté de ver algunos principios de ValidationEventHandler, pero funciona de alguna otra forma en CXF 2.0 y superior.

Respuesta

6

OK, Entonces, después de mucha investigación, he encontrado algunas maneras de manejar los errores de CXF.

*. ValidationEventHandler le brinda la posibilidad de lanzar su propia excepción en lugar de la estándar. PERO no puede cambiar el comportamiento de respuesta y no puede cambiar el formato de respuesta SOAP.

*. Otra forma de alterar el manejo de errores es crear su propio interceptor. El flujo de trabajo de CXF se basa en la cadena de interceptores. Hay 4 tipos de interceptores: inInterceptor, outInterceptor, inFaultInterceptor y outFaultInterceptor.

Usando algunos hacks inteligentes puede cambiar el flujo de trabajo creando su propio interceptor (agregándolo a la cadena), y eliminar el interceptor estándar de la cadena (si conoce su nombre de clase). Entonces puedes hacer todo lo que necesites.

PERO en la medida en que todos estos interceptores responden manualmente (xmlWriter.writeStartElement() etc) podría ser un gran desafío escribir sus propios interceptores para cada fase de flujo. Podría ser un gran montón de trabajo.

Desafortunadamente, no he encontrado buena referencia sobre interceptores CXF.

Otra cosa: si necesita devolver una respuesta regular en lugar de SOAPFaultException puede necesitar información adicional como: servicio real que devuelve esta respuesta, parámetros de servicio aprobados, etc. No he encontrado esta información en parámetros accesibles en interceptores . Y, seguramente, al hacerlo, engañará al código del cliente que devolverá OK en lugar de excepción real.

*. Diseñar su wsdl con todos los parámetros como texto puede ser una solución muy poco buena:

a. El consumidor de sus servicios puede ser realmente confuso si no hay tipos de datos y reglas de validación en wsdl.

b. Necesitarás 'reinventar la rueda' para la validación. Quiero decir que necesitarás codificar tu propio validador que podría ser muy difícil con algunas reglas complicadas. Al mismo tiempo, XSD tiene todas estas validaciones implementadas y bien probadas.

Y finalmente sobre mi situación: lo discutimos con el administrador de requisitos y decidimos permitir a CXF lanzar sus propias excepciones estándar si los requisitos del esquema XML violaban en la solicitud. Es una buena solución porque ahora estamos utilizando todo el poder de la validación de XSD y no perdemos el tiempo en trabajos complicados e inútiles.

Muchas gracias a @ericacm por su respuesta.

+0

Gracias por resumir la investigación que ha realizado sobre este tema. Ahora estoy enfrentando un desafío similar. – Withheld

1

Sin duda puede generar una mejor respuesta de error que la predeterminada usando ValidationEventHandler y arrojando una falla que cumpla con la especificación de falla JAX-WS. Pero solo te permitirá personalizar mucho: habrá algunos elementos sobre los que no tienes control. Por ejemplo, aquí está la respuesta ValidationEventHandler de una de mis aplicaciones:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
     <soap:Fault> 
     <faultcode>soap:Client</faultcode> 
     <faultstring>Errors in request</faultstring> 
     <detail> 
      <ns2:ValidationFault xmlns:ns2="http://notification.ws.foo.com/"> 
       <errors> 
        <error> 
        <inputElement>topicId</inputElement> 
        <errorMessage>java.lang.NumberFormatException: For input string: "" [line:6]</errorMessage> 
        </error> 
       </errors> 
      </ns2:ValidationFault> 
     </detail> 
     </soap:Fault> 
    </soap:Body> 
</soap:Envelope> 

No se puede hacer nada acerca de los elementos <soap:Fault>, <faultcode> and <faultstring>. Pero todo de <ValidationFault> a </ValidationFault> es personalizado.

Si necesita tener un control más detallado de la respuesta, debe cambiar el tipo de campo de numérico a cadena y luego validar su código en lugar de dejar que el unmarshaller detecte el error.

Sí, estoy de acuerdo, forzar que sea una cadena sería una mierda, pero si la respuesta tiene que ser exactamente lo que especificó anteriormente, no será posible sin profundizar en CXF que la capa JAX-WS (por ejemplo usando un interceptor).

+0

Gracias por la respuesta. Y tengo algunos comentarios al respecto. Sí, ValidationEventHandler te brinda la posibilidad de lanzar tu propia excepción en lugar de la estándar. Pero no puede ayudarlo si quiere reescribir completamente el mensaje de respuesta. Pero si recibimos todos los elementos de cadena, todos nuestros objetos generados contendrán todas estas cadenas y luego tendremos que "reinventar la rueda" para convertirlos y validarlos. Por otro lado, ¿cómo los consumidores de nuestros servicios web entenderán cuáles son los requisitos para los campos? A través de comentarios en el archivo WSDL? Entonces, IMO, cadenas no es realmente una buena decisión. –

+0

Respuesta actualizada. – sourcedelica

Cuestiones relacionadas