Capturar Mensajes SOAP con CXF

Hola a todos, hace algún tiempo necesite capturar un mensaje SOAP desde el código y poder conocer desde su cabecera hasta su contenido para poderlo manipular, al revisar información para implementarlo en CXF con Spring realice lo siguiente:

1.) Crear un clase Java

import javax.xml.namespace.QName;
import javax.xml.soap.*;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.ws.soap.SOAPFaultException;
import java.util.Set;

/**
*
*/
public class HandlerChain implements SOAPHandler<SOAPMessageContext> {


    public boolean handleMessage(SOAPMessageContext context) {

     System.out.println("Server : handleMessage()......");

     Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

     //for response message only, true for outbound messages, false for inbound
     if(!isRequest){

     try{
         SOAPMessage soapMsg = context.getMessage();
         SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
       SOAPHeader soapHeader = soapEnv.getHeader();
       System.out.println("Msg " + soapMsg.getSOAPHeader());

         //if no header, add one
         if (soapHeader == null){
                 soapHeader = soapEnv.addHeader();
                 //throw exception
                 generateSOAPErrMessage(soapMsg, "No SOAP header.");
          }

         }catch(SOAPException e){
             System.err.println(e);
         }

     }

       return true;
     }


     public boolean handleFault(SOAPMessageContext context) {

         System.out.println("Server : handleFault()......");

         return true;
     }


     public void close(MessageContext context) {
         System.out.println("Server : close()......");
     }


     public Set<QName> getHeaders() {
         System.out.println("Server : getHeaders()......");
         return null;
     }

      private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
        try {
           SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
           SOAPFault soapFault = soapBody.addFault();
           soapFault.setFaultString(reason);
           throw new SOAPFaultException(soapFault);
        }
        catch(SOAPException e) { }
     }

 }

2.) Crear un XML con lo siguiente (El "class_path" se debe reemplazar por la ruta donde se haya creado la clase del punto uno):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains
    xmlns:javaee="http://java.sun.com/xml/ns/javaee"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <javaee:handler-chain>
    <javaee:handler>
     <javaee:handler-class>class_path.HandlerChain</javaee:handler-class>
    </javaee:handler>
 </javaee:handler-chain>
</javaee:handler-chains> 
3.) En la implementación del WS se coloca lo siguiente:

@HandlerChain(file="/handler-chain.xml")

////Agregar Header SOAP
List<Header> headers = new ArrayList<Header>();
Header dummyHeader = new Header(new QName("uri:org.apache.cxf", "dummy"), "decapitated",
                               new JAXBDataBinding(String.class));
headers.add(dummyHeader);

//server side:
context.getMessageContext().put(Header.HEADER_LIST, headers);

//client side:
((BindingProvider)proxy).getRequestContext().put(Header.HEADER_LIST, headers);


Esto en gran parte fue tomado del siguiente link:


Espero que esta información les ayude, y hasta una futura oportunidad.

Comentarios