¿Cómo agregar una identificación de mensaje única a la solicitud de jabón 1.2 si no está presente?

nuestro servicio web es utilizado por un sistema que no envía la identificación del mensaje correctamente. (¡no en la solicitud de jabón en absoluto!) Estoy buscando formas de agregar una identificación de mensaje si no está presente en la llamada real. Si no está presente, toda la llamada falla por el hecho de que una propiedad requerida no está presente.

¿Hay una manera fácil de lograr esto?

preguntado el 02 de mayo de 12 a las 19:05

¿Quieres algo para el lado del cliente o para el lado del servidor? Si lo quiere en el lado del servidor, ¿por qué no simplemente establecer una identificación antes de la validación? -

En el lado del servidor, necesito agregarlo cuando un cliente llame a nuestro servicio web. ¿Cómo puedo hacer esto antes de la validación? -

¿Cómo se hace la validación? ¿Estamos hablando de la validación del esquema, por lo que algún atributo marcado como obligatorio no está presente? El valor predeterminado de SOAP se envía de vuelta al cliente. -

No estoy seguro de cómo se realiza la validación, mi servidor se queja de que falta un campo obligatorio. El Id. del mensaje, por lo que me gustaría completar este Id. del mensaje cuando no esté presente. -

El mensaje de error es: org.apache.cxf.binding.soap.SoapFault: un encabezado obligatorio que representa una propiedad de direccionamiento de mensajes no está presente -

1 Respuestas

Encontré una solución aquí, pero eso no parece funcionar.

Se me ocurrió esta solución que funciona para mí: cree un interceptor que verifique el encabezado MessageID y lo agregue al mensaje si no existe:

package my.package;

import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.headers.Header;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class HeaderInterceptor extends AbstractPhaseInterceptor<Message> {

    private static final String SOAP_HEADER_KEY = "org.apache.cxf.headers.Header.list";
    private static final String NAMESPACE_URI   = "http://www.w3.org/2005/08/addressing";
    private static final String QUALIFIED_NAME  = "wsa:MessageID";
    private static final String LOCAL_NAME      = "MessageID";

    public HeaderInterceptor() {
        // phases: http://cxf.apache.org/docs/interceptors.html
        // 'pre protocol' seems to be the best moment to check the header, if we do it earlier the headers don't exist in the message object so we can't re-use the 'owner document'
        // if we do it later the unmarshalMAPs method (in MAPCodec.java) will already have processed the headers and will not process our added header
        super(Phase.PRE_PROTOCOL);
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        ArrayList<SoapHeader> headers = (ArrayList<SoapHeader>) message.get(SOAP_HEADER_KEY);

        // if the header doesn't exist and we have at least one header to access 'owner document' we can create and add our own MessageID header
        if(!messageIdHeaderExists(headers) && headers.size() > 0) {
            Element existingHeaderElement = (Element) headers.get(0).getObject();

            // use the existing header element to create our own MessageID header with random UUID
            Element element = existingHeaderElement.getOwnerDocument().createElementNS(NAMESPACE_URI, QUALIFIED_NAME);
            element.appendChild(existingHeaderElement.getOwnerDocument().createTextNode("uuid:" + UUID.randomUUID().toString()));

            QName qname = new QName(NAMESPACE_URI, LOCAL_NAME);
            SoapHeader header = new SoapHeader(qname, element);

            // by default a SoapHeader is created with 'direction out'
            header.setDirection(Header.Direction.DIRECTION_IN);

            headers.add(header);
        }
    }

    /**
     * Checks if the MessageID header exists in the list of headers.
     *
     * @param headers list of headers
     * @return true if the MessageID header exists, false if not
     */
    private Boolean messageIdHeaderExists(ArrayList<SoapHeader> headers) {
        for(SoapHeader header:headers) {
            if(header.getName().getLocalPart().equalsIgnoreCase(LOCAL_NAME)) {
                return true;
            }
        }
        return false;
    }        

}

Defina el interceptor en su contexto Spring:

<bean id="headerInterceptor" class="my.package.HeaderInterceptor" />

<jaxws:endpoint implementor="#service" address="/ws">
    <jaxws:inInterceptors>
        <ref bean="headerInterceptor" />
    </jaxws:inInterceptors>
</jaxws:endpoint>

Probado con CXF versión 2.6.1. Más información sobre interceptores: http://cxf.apache.org/docs/interceptors.html

respondido 11 mar '14, 07:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.