Te llega un mensaje SOAP, y lo tienes que modificar porque hay una coma que esta en mal sitio. Vamos a usar Interceptors para ello.
Este es el mensaje que me llega y que quiero modificar:
<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <soapenv:Fault> <faultcode>env:Server</faultcode> <faultstring>0301 - Organismo no autorizado 'XXXXXXXX' 'CDISFWS01'</faultstring> <faultactor>CDISFWS01</faultactor> <detail> <Atributos xmlns="http://www.map.es/scsp/esquemas/V2/soapfaultatributos"> <IdPeticion>1390410889105</IdPeticion> <NumElementos>1</NumElementos> <TimeStamp>2014-01-22T18:14:20.651+01:00</TimeStamp> <Estado> <CodigoEstado>0301</CodigoEstado> <CodigoEstadoSecundario /> <LiteralError>Organismo no autorizado 'XXXXXXXX' 'CDISFWS01'</LiteralError> <TiempoEstimadoRespuesta>0</TiempoEstimadoRespuesta> </Estado> <CodigoCertificado>CDISFWS01</CodigoCertificado> </Atributos> </detail> </soapenv:Fault> </soapenv:Body> </soapenv:Envelope>
Lo que esta mal:
env:Server
Como debiera esta bien:
soapenv:Server
<?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <soapenv:Fault> <faultcode>soapenv:Server</faultcode> <faultstring>0301 - Organismo no autorizado 'XXXXXXXX' 'CDISFWS01'</faultstring> <faultactor>CDISFWS01</faultactor> <detail> <Atributos xmlns="http://www.map.es/scsp/esquemas/V2/soapfaultatributos"> <IdPeticion>1390410889105</IdPeticion> <NumElementos>1</NumElementos> <TimeStamp>2014-01-22T18:14:20.651+01:00</TimeStamp> <Estado> <CodigoEstado>0301</CodigoEstado> <CodigoEstadoSecundario /> <LiteralError>Organismo no autorizado 'XXXXXXXX' 'CDISFWS01'</LiteralError> <TiempoEstimadoRespuesta>0</TiempoEstimadoRespuesta> </Estado> <CodigoCertificado>CDISFWS01</CodigoCertificado> </Atributos> </detail> </soapenv:Fault> </soapenv:Body> </soapenv:Envelope>
Utilizo esta clase que algun compañero de profesion dejo en stackoverflow.com. Yo simplemente he modificado el uso del log.
package una.ruta.a.un.paquete; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.io.IOUtils; import org.apache.cxf.binding.soap.interceptor.SoapPreProtocolOutInterceptor; import org.apache.cxf.io.CachedOutputStream; import org.apache.cxf.message.Message; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.slf4j.LoggerFactory; public abstract class MessageChangeInterceptor extends AbstractPhaseInterceptor<Message> { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(MessageChangeInterceptor.class); public MessageChangeInterceptor() { super(Phase.PRE_STREAM); addBefore(SoapPreProtocolOutInterceptor.class.getName()); } protected abstract String changeOutboundMessage(String currentEnvelope); protected abstract String changeInboundMessage(String currentEnvelope); public void handleMessage(Message message) { boolean isOutbound = false; isOutbound = message == message.getExchange().getOutMessage() || message == message.getExchange().getOutFaultMessage(); if (isOutbound) { OutputStream os = message.getContent(OutputStream.class); CachedStream cs = new CachedStream(); message.setContent(OutputStream.class, cs); message.getInterceptorChain().doIntercept(message); try { cs.flush(); IOUtils.closeQuietly(cs); CachedOutputStream csnew = (CachedOutputStream) message.getContent(OutputStream.class); String currentEnvelopeMessage = IOUtils.toString(csnew.getInputStream(), "UTF-8"); csnew.flush(); IOUtils.closeQuietly(csnew); LOGGER.debug("Outbound message: " + currentEnvelopeMessage); String res = changeOutboundMessage(currentEnvelopeMessage); if (res != null) { LOGGER.debug("Outbound message has been changed: " + res); } res = res != null ? res : currentEnvelopeMessage; InputStream replaceInStream = IOUtils.toInputStream(res, "UTF-8"); IOUtils.copy(replaceInStream, os); replaceInStream.close(); IOUtils.closeQuietly(replaceInStream); os.flush(); message.setContent(OutputStream.class, os); IOUtils.closeQuietly(os); } catch (IOException ioe) { LOGGER.warn("Unable to perform change.", ioe); throw new RuntimeException(ioe); } } else { try { InputStream is = message.getContent(InputStream.class); String currentEnvelopeMessage = IOUtils.toString(is, "UTF-8"); IOUtils.closeQuietly(is); LOGGER.debug("Inbound message: " + currentEnvelopeMessage); String res = changeInboundMessage(currentEnvelopeMessage); if (res != null) { LOGGER.debug("Inbound message has been changed: " + res); } res = res != null ? res : currentEnvelopeMessage; is = IOUtils.toInputStream(res, "UTF-8"); message.setContent(InputStream.class, is); IOUtils.closeQuietly(is); } catch (IOException ioe) { LOGGER.warn("Unable to perform change.", ioe); throw new RuntimeException(ioe); } } } public void handleFault(Message message) { } private class CachedStream extends CachedOutputStream { public CachedStream() { super(); } protected void doFlush() throws IOException { currentStream.flush(); } protected void doClose() throws IOException { } protected void onWrite() throws IOException { } } }
Y la clase que hereda de la anterior, y realiza el cambio requerido:
package una.ruta.a.un.paquete; import org.slf4j.LoggerFactory; public class InterceptorInSoapFaultBug extends MessageChangeInterceptor { private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(InterceptorInSoapFaultBug.class); @Override protected String changeOutboundMessage(String currentEnvelope) { // TODO Auto-generated method stub return null; } @Override protected String changeInboundMessage(String currentEnvelope) { if((currentEnvelope != null) && (currentEnvelope.contains(">env:Server<"))){ LOGGER.info("Debido a un bug en el mensaje SoapFault de este servicio. se procede a cambiar la etiqueta "env:Server" por "soapenv:Server"."); currentEnvelope = currentEnvelope.replace(">env:Server<", ">soapenv:Server<"); } return currentEnvelope; } }
Posteriormente en el fichero de configuracion de Spring tendrias que invocarlo:
<!-- ... --> <bean id="bugSoapFault" class="una.ruta.a.un.paquete.InterceptorInSoapFaultBug" /> <!-- ... --> <jaxws:client id="clientPaxaseConsultaIdentidad" address="#{url}" serviceClass="es.map.xml_schemas.PeticionPortType"> <!-- <jaxws:properties> --> <!-- <entry key="schema-validation-enabled" value="true" /> --> <!-- </jaxws:properties> --> <jaxws:inFaultInterceptors> <ref bean="logInbound" /> <ref bean="bugSoapFault" /> </jaxws:inFaultInterceptors> <jaxws:inInterceptors> <!-- cierra todas las etiquetas y rellena lo que falta -->