简体   繁体   English

在 Spring-WS 中同时支持 SOAP 1.1 和 SOAP 1.2 消息

[英]Support both SOAP 1.1 and SOAP 1.2 messages in Spring-WS

Looked all over for a response to my problem with little success.到处寻找对我的问题的回应,但收效甚微。

I have a Spring boot app which needs to expose both SOAP 1.1 and SOAP 1.2 endpoints.我有一个 Spring Boot 应用程序,它需要同时公开SOAP 1.1SOAP 1.2端点。 I understand the SOAP version can be configured on the WebServiceMessageFactory bean (currently using SAAJ), but this sets a fixed SOAP version for all endpoints.我知道可以在WebServiceMessageFactory bean 上配置 SOAP 版本(当前使用 SAAJ),但这会为所有端点设置一个固定的 SOAP 版本。

Is there a way to achieve this?有没有办法做到这一点?

Thank you谢谢

Doesn't seem to be a built in way of doing this.似乎不是这样做的内置方式。

I ended up subclassing SaajSoapMessageFactory and declaring that as a Bean, like this:我最终继承了SaajSoapMessageFactory并将其声明为 Bean,如下所示:

@Bean("messageFactory")
public SoapMessageFactory messageFactory() {
   var messageFactory = new DualProtocolSaajSoapMessageFactory();

   return messageFactory;
}

This new class is a copy of SaajSoapMessageFactory with a few changes: - It internally has two message factories, one for 1.1 and one for 1.2这个新类是 SaajSoapMessageFactory 的副本,有一些更改: - 它内部有两个消息工厂,一个用于 1.1,一个用于 1.2

public DualProtocolSaajSoapMessageFactory() {
    super();

    try {
        messageFactory11 = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
        messageFactory12 = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
    } catch (Exception ex) {
        throw new SoapMessageCreationException("Could not create SAAJ MessageFactory: " + ex.getMessage(), ex);
    }
}

And then, basically, just override createWebServiceMessage:然后,基本上,只需覆盖 createWebServiceMessage:

@Override
public SaajSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
    MimeHeaders mimeHeaders = parseMimeHeaders(inputStream);
    try {
        inputStream = checkForUtf8ByteOrderMark(inputStream);
        SOAPMessage saajMessage = null;

        if (mimeHeaders.getHeader(HttpHeaders.CONTENT_TYPE)[0].contains(MimeTypeUtils.TEXT_XML_VALUE)) {
            saajMessage = messageFactory11.createMessage(mimeHeaders, inputStream);
        } else {
            saajMessage = messageFactory12.createMessage(mimeHeaders, inputStream);
        }
...snip

A little hacky, but does what it needs to do.有点hacky,但做了它需要做的事情。

I use ThreadLocal for multi-threaded use我使用 ThreadLocal 进行多线程使用

public class DualProtocolSaajSoapMessageFactory
    implements SoapMessageFactory, InitializingBean {

ThreadLocal<MessageFactory> threadLocalValue = new ThreadLocal<>();

private String messageFactoryProtocol;
private boolean langAttributeOnSoap11FaultString = true;
private Map<String, ?> messageProperties;
MessageFactory messageFactory11;
MessageFactory messageFactory12;

public DualProtocolSaajSoapMessageFactory() {
    super();

    try {
        messageFactory11 = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
        messageFactory12 = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
    } catch (Exception ex) {
        throw new SoapMessageCreationException("Could not create SAAJ MessageFactory: " + ex.getMessage(), ex);
    }
}

public void setMessageProperties(Map<String, ?> messageProperties) {
    this.messageProperties = messageProperties;
}

public void setLangAttributeOnSoap11FaultString(boolean langAttributeOnSoap11FaultString) {
    this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString;
}

private MessageFactory getMessageFactoryThreadLocal() {
    return threadLocalValue.get();
}

public void setSoapVersion(SoapVersion version) {
    if (SaajUtils.getSaajVersion() >= 2) {
        if (SoapVersion.SOAP_11 == version) {
            this.messageFactoryProtocol = "SOAP 1.1 Protocol";
        } else {
            if (SoapVersion.SOAP_12 != version) {
                throw new IllegalArgumentException("Invalid version [" + version + "]. Expected the SOAP_11 or SOAP_12 constant");
            }

            this.messageFactoryProtocol = "SOAP 1.2 Protocol";
        }
    } else if (SoapVersion.SOAP_11 != version) {
        throw new IllegalArgumentException("SAAJ 1.1 and 1.2 only support SOAP 1.1");
    }

}

public void afterPropertiesSet() {
}

public SaajSoapMessage createWebServiceMessage() {
    try {
        MessageFactory messageFactory = getMessageFactoryThreadLocal();
        SOAPMessage saajMessage = messageFactory.createMessage();
        this.postProcess(saajMessage);
        return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString, messageFactory);
    } catch (SOAPException var2) {
        throw new SoapMessageCreationException("Could not create empty message: " + var2.getMessage(), var2);
    }
}

@Override
public SaajSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
    MimeHeaders mimeHeaders = this.parseMimeHeaders(inputStream);
    try {
        inputStream = checkForUtf8ByteOrderMark(inputStream);
        SOAPMessage saajMessage = null;
        if (mimeHeaders.getHeader(HttpHeaders.CONTENT_TYPE)[0].contains(MimeTypeUtils.TEXT_XML_VALUE)) {
            saajMessage = messageFactory11.createMessage(mimeHeaders, inputStream);
            threadLocalValue.set(messageFactory11);
        } else {
            saajMessage = messageFactory12.createMessage(mimeHeaders, inputStream);
            threadLocalValue.set(messageFactory12);
        }

        saajMessage.getSOAPPart().getEnvelope();
        this.postProcess(saajMessage);
        return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString, getMessageFactoryThreadLocal());
    } catch (SOAPException var7) {
        String contentType = StringUtils.arrayToCommaDelimitedString(mimeHeaders.getHeader("Content-Type"));
        if (contentType.contains("startinfo")) {
            contentType = contentType.replace("startinfo", "start-info");
            mimeHeaders.setHeader("Content-Type", contentType);

            try {
                SOAPMessage saajMessage = getMessageFactoryThreadLocal().createMessage(mimeHeaders, inputStream);
                this.postProcess(saajMessage);
                return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString);
            } catch (SOAPException var6) {
            }
        }

        SAXParseException parseException = this.getSAXParseException(var7);
        if (parseException != null) {
            throw new InvalidXmlException("Could not parse XML", parseException);
        } else {
            throw new SoapMessageCreationException("Could not create message from InputStream: " + var7.getMessage(), var7);
        }
    }
}

private SAXParseException getSAXParseException(Throwable ex) {
    if (ex instanceof SAXParseException) {
        return (SAXParseException) ex;
    } else {
        return ex.getCause() != null ? this.getSAXParseException(ex.getCause()) : null;
    }
}

private MimeHeaders parseMimeHeaders(InputStream inputStream) throws IOException {
    MimeHeaders mimeHeaders = new MimeHeaders();
    if (inputStream instanceof TransportInputStream) {
        TransportInputStream transportInputStream = (TransportInputStream) inputStream;
        Iterator headerNames = transportInputStream.getHeaderNames();

        while (headerNames.hasNext()) {
            String headerName = (String) headerNames.next();
            Iterator headerValues = transportInputStream.getHeaders(headerName);

            while (headerValues.hasNext()) {
                String headerValue = (String) headerValues.next();
                StringTokenizer tokenizer = new StringTokenizer(headerValue, ",");

                while (tokenizer.hasMoreTokens()) {
                    mimeHeaders.addHeader(headerName, tokenizer.nextToken().trim());
                }
            }
        }
    }

    return mimeHeaders;
}

private InputStream checkForUtf8ByteOrderMark(InputStream inputStream) throws IOException {
    PushbackInputStream pushbackInputStream = new PushbackInputStream(new BufferedInputStream(inputStream), 3);
    byte[] bytes = new byte[3];

    int bytesRead;
    int n;
    for (bytesRead = 0; bytesRead < bytes.length; bytesRead += n) {
        n = pushbackInputStream.read(bytes, bytesRead, bytes.length - bytesRead);
        if (n <= 0) {
            break;
        }
    }

    if (bytesRead > 0 && !this.isByteOrderMark(bytes)) {
        pushbackInputStream.unread(bytes, 0, bytesRead);
    }

    return pushbackInputStream;
}

private boolean isByteOrderMark(byte[] bytes) {
    return bytes.length == 3 && bytes[0] == -17 && bytes[1] == -69 && bytes[2] == -65;
}

protected void postProcess(SOAPMessage soapMessage) throws SOAPException {
    if (!CollectionUtils.isEmpty(this.messageProperties)) {
        Iterator var2 = this.messageProperties.entrySet().iterator();

        while (var2.hasNext()) {
            Map.Entry<String, ?> entry = (Map.Entry) var2.next();
            soapMessage.setProperty((String) entry.getKey(), entry.getValue());
        }
    }

    if ("SOAP 1.1 Protocol".equals(this.messageFactoryProtocol)) {
        MimeHeaders headers = soapMessage.getMimeHeaders();
        if (ObjectUtils.isEmpty(headers.getHeader("SOAPAction"))) {
            headers.addHeader("SOAPAction", "\"\"");
        }
    }

}

public String toString() {
    StringBuilder builder = new StringBuilder("SaajSoapMessageFactory[");
    builder.append(SaajUtils.getSaajVersionString());
    if (SaajUtils.getSaajVersion() >= 2) {
        builder.append(',');
        builder.append(this.messageFactoryProtocol);
    }

    builder.append(']');
    return builder.toString();
}}
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Map.Entry;
import javax.xml.soap.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpHeaders;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.InvalidXmlException;
import org.springframework.ws.soap.SoapMessageCreationException;
import org.springframework.ws.soap.SoapMessageFactory;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.support.SaajUtils;
import org.springframework.ws.transport.TransportInputStream;
import org.xml.sax.SAXParseException;
/*Copy of class SaajSoapMessageFactory to override method createWebServiceMessage(InputStream inputStream)*/
public class DualProtocolSaajSoapMessageFactory implements SoapMessageFactory, InitializingBean {
    private static final Log logger = LogFactory.getLog(DualProtocolSaajSoapMessageFactory.class);
    private MessageFactory messageFactory;
    private String messageFactoryProtocol;
    private boolean langAttributeOnSoap11FaultString = true;
    private Map<String, ?> messageProperties;
    MessageFactory messageFactory11;
    MessageFactory messageFactory12;
    public DualProtocolSaajSoapMessageFactory() {
        super();

        try {
            messageFactory11 = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
            messageFactory12 = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        } catch (Exception ex) {
            throw new SoapMessageCreationException("Could not create SAAJ MessageFactory: " + ex.getMessage(), ex);
        }
    }

    public DualProtocolSaajSoapMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }

    public MessageFactory getMessageFactory() {
        return this.messageFactory;
    }

    public void setMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }

    public void setMessageProperties(Map<String, ?> messageProperties) {
        this.messageProperties = messageProperties;
    }

    public void setLangAttributeOnSoap11FaultString(boolean langAttributeOnSoap11FaultString) {
        this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString;
    }

    public void setSoapVersion(SoapVersion version) {
        if (SaajUtils.getSaajVersion() >= 2) {
            if (SoapVersion.SOAP_11 == version) {
                this.messageFactoryProtocol = "SOAP 1.1 Protocol";
            } else {
                if (SoapVersion.SOAP_12 != version) {
                    throw new IllegalArgumentException("Invalid version [" + version + "]. Expected the SOAP_11 or SOAP_12 constant");
                }

                this.messageFactoryProtocol = "SOAP 1.2 Protocol";
            }
        } else if (SoapVersion.SOAP_11 != version) {
            throw new IllegalArgumentException("SAAJ 1.1 and 1.2 only support SOAP 1.1");
        }

    }

    public void afterPropertiesSet() {
        if (this.messageFactory == null) {
            try {
                if (SaajUtils.getSaajVersion() >= 2) {
                    if (!StringUtils.hasLength(this.messageFactoryProtocol)) {
                        this.messageFactoryProtocol = "SOAP 1.1 Protocol";
                    }

                    if (logger.isInfoEnabled()) {
                        logger.info("Creating SAAJ 1.3 MessageFactory with " + this.messageFactoryProtocol);
                    }

                    this.messageFactory = MessageFactory.newInstance(this.messageFactoryProtocol);
                } else if (SaajUtils.getSaajVersion() == 1) {
                    logger.info("Creating SAAJ 1.2 MessageFactory");
                    this.messageFactory = MessageFactory.newInstance();
                } else {
                    if (SaajUtils.getSaajVersion() != 0) {
                        throw new IllegalStateException("SaajSoapMessageFactory requires SAAJ 1.1, which was not found on the classpath");
                    }

                    logger.info("Creating SAAJ 1.1 MessageFactory");
                    this.messageFactory = MessageFactory.newInstance();
                }
            } catch (NoSuchMethodError var2) {
                throw new SoapMessageCreationException("Could not create SAAJ MessageFactory. Is the version of the SAAJ specification interfaces [" + SaajUtils.getSaajVersionString() + "] the same as the version supported by the application server?", var2);
            } catch (SOAPException var3) {
                throw new SoapMessageCreationException("Could not create SAAJ MessageFactory: " + var3.getMessage(), var3);
            }
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Using MessageFactory class [" + this.messageFactory.getClass().getName() + "]");
        }

    }

    public SaajSoapMessage createWebServiceMessage() {
        try {
            SOAPMessage saajMessage = this.messageFactory.createMessage();
            this.postProcess(saajMessage);
            return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString, this.messageFactory);
        } catch (SOAPException var2) {
            throw new SoapMessageCreationException("Could not create empty message: " + var2.getMessage(), var2);
        }
    }
    /*Override default property oenter code heref createWebServiceMessage*/
    public SaajSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
        MimeHeaders mimeHeaders = this.parseMimeHeaders(inputStream);
        try {
            inputStream = checkForUtf8ByteOrderMark(inputStream);
            SOAPMessage saajMessage = null;
            if (mimeHeaders.getHeader(HttpHeaders.CONTENT_TYPE)[0].contains(MimeTypeUtils.TEXT_XML_VALUE)) {
                saajMessage = messageFactory11.createMessage(mimeHeaders, inputStream);
            } else {
                saajMessage = messageFactory12.createMessage(mimeHeaders, inputStream);
            }
            saajMessage.getSOAPPart().getEnvelope();
            this.postProcess(saajMessage);
            return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString, this.messageFactory);
        } catch (SOAPException var7) {
            String contentType = StringUtils.arrayToCommaDelimitedString(mimeHeaders.getHeader("Content-Type"));
            if (contentType.contains("startinfo")) {
                contentType = contentType.replace("startinfo", "start-info");
                mimeHeaders.setHeader("Content-Type", contentType);

                try {
                    SOAPMessage saajMessage = this.messageFactory.createMessage(mimeHeaders, inputStream);
                    this.postProcess(saajMessage);
                    return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString);
                } catch (SOAPException var6) {
                }
            }

            SAXParseException parseException = this.getSAXParseException(var7);
            if (parseException != null) {
                throw new InvalidXmlException("Could not parse XML", parseException);
            } else {
                throw new SoapMessageCreationException("Could not create message from InputStream: " + var7.getMessage(), var7);
            }
        }
    }

    private SAXParseException getSAXParseException(Throwable ex) {
        if (ex instanceof SAXParseException) {
            return (SAXParseException)ex;
        } else {
            return ex.getCause() != null ? this.getSAXParseException(ex.getCause()) : null;
        }
    }

    private MimeHeaders parseMimeHeaders(InputStream inputStream) throws IOException {
        MimeHeaders mimeHeaders = new MimeHeaders();
        if (inputStream instanceof TransportInputStream) {
            TransportInputStream transportInputStream = (TransportInputStream)inputStream;
            Iterator headerNames = transportInputStream.getHeaderNames();

            while(headerNames.hasNext()) {
                String headerName = (String)headerNames.next();
                Iterator headerValues = transportInputStream.getHeaders(headerName);

                while(headerValues.hasNext()) {
                    String headerValue = (String)headerValues.next();
                    StringTokenizer tokenizer = new StringTokenizer(headerValue, ",");

                    while(tokenizer.hasMoreTokens()) {
                        mimeHeaders.addHeader(headerName, tokenizer.nextToken().trim());
                    }
                }
            }
        }

        return mimeHeaders;
    }

    private InputStream checkForUtf8ByteOrderMark(InputStream inputStream) throws IOException {
        PushbackInputStream pushbackInputStream = new PushbackInputStream(new BufferedInputStream(inputStream), 3);
        byte[] bytes = new byte[3];

        int bytesRead;
        int n;
        for(bytesRead = 0; bytesRead < bytes.length; bytesRead += n) {
            n = pushbackInputStream.read(bytes, bytesRead, bytes.length - bytesRead);
            if (n <= 0) {
                break;
            }
        }

        if (bytesRead > 0 && !this.isByteOrderMark(bytes)) {
            pushbackInputStream.unread(bytes, 0, bytesRead);
        }

        return pushbackInputStream;
    }

    private boolean isByteOrderMark(byte[] bytes) {
        return bytes.length == 3 && bytes[0] == -17 && bytes[1] == -69 && bytes[2] == -65;
    }

    protected void postProcess(SOAPMessage soapMessage) throws SOAPException {
        if (!CollectionUtils.isEmpty(this.messageProperties)) {
            Iterator var2 = this.messageProperties.entrySet().iterator();

            while(var2.hasNext()) {
                Entry<String, ?> entry = (Entry)var2.next();
                soapMessage.setProperty((String)entry.getKey(), entry.getValue());
            }
        }

        if ("SOAP 1.1 Protocol".equals(this.messageFactoryProtocol)) {
            MimeHeaders headers = soapMessage.getMimeHeaders();
            if (ObjectUtils.isEmpty(headers.getHeader("SOAPAction"))) {
                headers.addHeader("SOAPAction", "\"\"");
            }
        }

    }

    public String toString() {
        StringBuilder builder = new StringBuilder("SaajSoapMessageFactory[");
        builder.append(SaajUtils.getSaajVersionString());
        if (SaajUtils.getSaajVersion() >= 2) {
            builder.append(',');
            builder.append(this.messageFactoryProtocol);
        }

        builder.append(']');
        return builder.toString();
    }
}
Above will fail if you have concurrent request of soap1.1 and soap1.2, to avoid that the messageFactory should be created with @RequestScope, for example.
    

    @Bean
    @RequestScope
    public SoapMessageFactory  messageFactory() {
         logger.info("Calling SoapMessageFactory Bean");
        DualProtocolSaajSoapMessageFactory s = new DualProtocolSaajSoapMessageFactory();
        return s;
    }


and the full Spring WS config java file will be like below

package com.hps.powercard;

import java.util.List;

import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jndi.JndiTemplate;
import org.springframework.web.context.annotation.RequestScope;
import org.springframework.ws.config.annotation.EnableWs;
import org.springframework.ws.config.annotation.WsConfigurerAdapter;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.soap.SoapMessageFactory;
import org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor;
import org.springframework.ws.transport.http.MessageDispatcherServlet;
import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition;
import org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition;
import org.springframework.ws.wsdl.wsdl11.Wsdl11Definition;
import org.springframework.xml.xsd.SimpleXsdSchema;
import org.springframework.xml.xsd.XsdSchema;




@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
    private static final Log logger = LogFactory.getLog(WebServiceConfig.class);
    @Bean
    public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
        MessageDispatcherServlet servlet = new MessageDispatcherServlet();
        servlet.setApplicationContext(applicationContext);
        servlet.setTransformWsdlLocations(true);
        return new ServletRegistrationBean(servlet, "/services/*");
    }
    @Bean(name = "AlShayaPosWS")
      public Wsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
        SimpleWsdl11Definition wsdl11Definition = new SimpleWsdl11Definition(new ClassPathResource("AlShayaPosWS.wsdl"));
        
        return wsdl11Definition;
      }
    @Bean
    @RequestScope
    public SoapMessageFactory  messageFactory() {
         logger.info("Calling SoapMessageFactory Bean");
        DualProtocolSaajSoapMessageFactory s = new DualProtocolSaajSoapMessageFactory();
        return s;
    }   
    @Bean
    public XsdSchema getBalanceDetailsSchema() {
        return new SimpleXsdSchema(new ClassPathResource("alshaya.xsd"));
    }
    /*@Bean(name = "AlShayaPosWS")
    public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema getBalanceDetailsSchema) {
        DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
        wsdl11Definition.setPortTypeName("AlShayaPosWSPortType");
        wsdl11Definition.setLocationUri("/ws");
        wsdl11Definition.setTargetNamespace("http://alshaya.ws.iface.bw.rs2.com");
        wsdl11Definition.setSchema(getBalanceDetailsSchema);
        return wsdl11Definition;
    }


    @Bean
    public XsdSchema getBalanceDetailsSchema() {
        return new SimpleXsdSchema(new ClassPathResource("alshayaws.xsd"));
    }*/
    @Bean
    public DataSource dataSource() throws NamingException { 
//        return (DataSource) new JndiTemplate().lookup("java://jdbc/PWCCFGDS");
        return (DataSource) new JndiTemplate().lookup("jdbc/PWCCFGDS");
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        jdbcTemplate.setResultsMapCaseInsensitive(true);
        return jdbcTemplate;
    }   
    @Override
    public void addInterceptors(List<EndpointInterceptor> interceptors) {
      PayloadValidatingInterceptor validatingInterceptor = new PayloadValidatingInterceptor();
      validatingInterceptor.setValidateRequest(true);
      validatingInterceptor.setValidateResponse(true);
      validatingInterceptor.setXsdSchema(getBalanceDetailsSchema());
      interceptors.add(validatingInterceptor);
      interceptors.add(new CustomEndpointInterceptor());
//      interceptors.add(new SOAP11CustomEndpointInterceptorAdapter());
//      interceptors.add(new SOAP12CustomEndpointInterceptorAdapter());
    }    
}


and the DualProtocolSaajSoapMessageFactory will be like below , i have just copy paste the above

package com.hps.powercard;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Map.Entry;
import javax.xml.soap.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.http.HttpHeaders;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.ws.InvalidXmlException;
import org.springframework.ws.soap.SoapMessageCreationException;
import org.springframework.ws.soap.SoapMessageFactory;
import org.springframework.ws.soap.SoapVersion;
import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.support.SaajUtils;
import org.springframework.ws.transport.TransportInputStream;
import org.xml.sax.SAXParseException;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
import java.util.Iterator;
public class DualProtocolSaajSoapMessageFactory implements SoapMessageFactory, InitializingBean {
    private static final Log logger = LogFactory.getLog(DualProtocolSaajSoapMessageFactory.class);
    private MessageFactory messageFactory;
    private String messageFactoryProtocol;
    private boolean langAttributeOnSoap11FaultString = true;
    private Map<String, ?> messageProperties;
    MessageFactory messageFactory11;
    MessageFactory messageFactory12;
    public DualProtocolSaajSoapMessageFactory() {
        super();

        try {
            messageFactory11 = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
            messageFactory12 = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
        } catch (Exception ex) {
            throw new SoapMessageCreationException("Could not create SAAJ MessageFactory: " + ex.getMessage(), ex);
        }
    }

    public DualProtocolSaajSoapMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }

    public MessageFactory getMessageFactory() {
        return this.messageFactory;
    }

    public void setMessageFactory(MessageFactory messageFactory) {
        this.messageFactory = messageFactory;
    }

    public void setMessageProperties(Map<String, ?> messageProperties) {
        this.messageProperties = messageProperties;
    }

    public void setLangAttributeOnSoap11FaultString(boolean langAttributeOnSoap11FaultString) {
        this.langAttributeOnSoap11FaultString = langAttributeOnSoap11FaultString;
    }

    public void setSoapVersion(SoapVersion version) {
        if (SaajUtils.getSaajVersion() >= 2) {
            if (SoapVersion.SOAP_11 == version) {
                this.messageFactoryProtocol = "SOAP 1.1 Protocol";
            } else {
                if (SoapVersion.SOAP_12 != version) {
                    throw new IllegalArgumentException("Invalid version [" + version + "]. Expected the SOAP_11 or SOAP_12 constant");
                }

                this.messageFactoryProtocol = "SOAP 1.2 Protocol";
            }
        } else if (SoapVersion.SOAP_11 != version) {
            throw new IllegalArgumentException("SAAJ 1.1 and 1.2 only support SOAP 1.1");
        }

    }

    public void afterPropertiesSet() {
        logger.info("Calling afterPropertiesSet()");
        if (this.messageFactory == null) {
            try {
                if (SaajUtils.getSaajVersion() >= 2) {
                    if (!StringUtils.hasLength(this.messageFactoryProtocol)) {
                        this.messageFactoryProtocol = "SOAP 1.1 Protocol";
                    }

                    if (logger.isInfoEnabled()) {
                        logger.info("Creating SAAJ 1.3 MessageFactory with " + this.messageFactoryProtocol);
                    }

                    this.messageFactory = MessageFactory.newInstance(this.messageFactoryProtocol);
                } else if (SaajUtils.getSaajVersion() == 1) {
                    logger.info("Creating SAAJ 1.2 MessageFactory");
                    this.messageFactory = MessageFactory.newInstance();
                } else {
                    if (SaajUtils.getSaajVersion() != 0) {
                        throw new IllegalStateException("SaajSoapMessageFactory requires SAAJ 1.1, which was not found on the classpath");
                    }

                    logger.info("Creating SAAJ 1.1 MessageFactory");
                    this.messageFactory = MessageFactory.newInstance();
                }
            } catch (NoSuchMethodError var2) {
                throw new SoapMessageCreationException("Could not create SAAJ MessageFactory. Is the version of the SAAJ specification interfaces [" + SaajUtils.getSaajVersionString() + "] the same as the version supported by the application server?", var2);
            } catch (SOAPException var3) {
                throw new SoapMessageCreationException("Could not create SAAJ MessageFactory: " + var3.getMessage(), var3);
            }
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Using MessageFactory class [" + this.messageFactory.getClass().getName() + "]");
        }

    }

    public SaajSoapMessage createWebServiceMessage() {
        logger.info("Calling createWebServiceMessage()");
        try {
            SOAPMessage saajMessage = this.messageFactory.createMessage();
            this.postProcess(saajMessage);
            return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString, this.messageFactory);
        } catch (SOAPException var2) {
            throw new SoapMessageCreationException("Could not create empty message: " + var2.getMessage(), var2);
        }
    }
    /*Override default property oenter code heref createWebServiceMessage*/
    public SaajSoapMessage createWebServiceMessage(InputStream inputStream) throws IOException {
        logger.info("Calling createWebServiceMessage(InputStream inputStream)");
        MimeHeaders mimeHeaders = this.parseMimeHeaders(inputStream);
        try {
            inputStream = checkForUtf8ByteOrderMark(inputStream);
            SOAPMessage saajMessage = null;
            System.out.println("Obtained Content-Type is :"+mimeHeaders.getHeader(HttpHeaders.CONTENT_TYPE)[0]);
            if (mimeHeaders.getHeader(HttpHeaders.CONTENT_TYPE)[0].contains(MimeTypeUtils.TEXT_XML_VALUE)) {
                logger.info("Obtained Protocol : SOAP 1.1 Protocol");
                this.messageFactoryProtocol = "SOAP 1.1 Protocol";
                this.messageFactory = MessageFactory.newInstance(this.messageFactoryProtocol);
                saajMessage = messageFactory11.createMessage(mimeHeaders, inputStream);
            }
            else if (mimeHeaders.getHeader(HttpHeaders.CONTENT_TYPE)[0].trim().toLowerCase().contains(MimeTypeUtils.TEXT_XML_VALUE)) {
                logger.info("Obtained Protocol : SOAP 1.1 Protocol");
                this.messageFactoryProtocol = "SOAP 1.1 Protocol";
                this.messageFactory = MessageFactory.newInstance(this.messageFactoryProtocol);
                saajMessage = messageFactory11.createMessage(mimeHeaders, inputStream);
            }            
            else if (mimeHeaders.getHeader(HttpHeaders.CONTENT_TYPE)[0].trim().toLowerCase().contains("text/xml")) {
                logger.info("Obtained Protocol : SOAP 1.1 Protocol");
                this.messageFactoryProtocol = "SOAP 1.1 Protocol";
                this.messageFactory = MessageFactory.newInstance(this.messageFactoryProtocol);
                saajMessage = messageFactory11.createMessage(mimeHeaders, inputStream);
            }              
            else {
                logger.info("Obtained Protocol : SOAP 1.2 Protocol");
                this.messageFactoryProtocol = "SOAP 1.2 Protocol";
                this.messageFactory = MessageFactory.newInstance(this.messageFactoryProtocol);
                saajMessage = messageFactory12.createMessage(mimeHeaders, inputStream);  
            }
            saajMessage.getSOAPPart().getEnvelope();
            this.postProcess(saajMessage);
            return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString, this.messageFactory);
        } catch (SOAPException var7) {
            String contentType = StringUtils.arrayToCommaDelimitedString(mimeHeaders.getHeader("Content-Type"));
            if (contentType.contains("startinfo")) {
                contentType = contentType.replace("startinfo", "start-info");
                mimeHeaders.setHeader("Content-Type", contentType);

                try {
                    SOAPMessage saajMessage = this.messageFactory.createMessage(mimeHeaders, inputStream);
                    this.postProcess(saajMessage);
                    return new SaajSoapMessage(saajMessage, this.langAttributeOnSoap11FaultString);
                } catch (SOAPException var6) {
                }
            }

            SAXParseException parseException = this.getSAXParseException(var7);
            if (parseException != null) {
                throw new InvalidXmlException("Could not parse XML", parseException);
            } else {
                throw new SoapMessageCreationException("Could not create message from InputStream: " + var7.getMessage(), var7);
            }
        }
    }

    private SAXParseException getSAXParseException(Throwable ex) {
        if (ex instanceof SAXParseException) {
            return (SAXParseException)ex;
        } else {
            return ex.getCause() != null ? this.getSAXParseException(ex.getCause()) : null;
        }
    }

    private MimeHeaders parseMimeHeaders(InputStream inputStream) throws IOException {
        MimeHeaders mimeHeaders = new MimeHeaders();
        if (inputStream instanceof TransportInputStream) {
            TransportInputStream transportInputStream = (TransportInputStream)inputStream;
            Iterator headerNames = transportInputStream.getHeaderNames();

            while(headerNames.hasNext()) {
                String headerName = (String)headerNames.next();
                Iterator headerValues = transportInputStream.getHeaders(headerName);

                while(headerValues.hasNext()) {
                    String headerValue = (String)headerValues.next();
                    StringTokenizer tokenizer = new StringTokenizer(headerValue, ",");

                    while(tokenizer.hasMoreTokens()) {
                        mimeHeaders.addHeader(headerName, tokenizer.nextToken().trim());
                    }
                }
            }
        }

        return mimeHeaders;
    }

    private InputStream checkForUtf8ByteOrderMark(InputStream inputStream) throws IOException {
        PushbackInputStream pushbackInputStream = new PushbackInputStream(new BufferedInputStream(inputStream), 3);
        byte[] bytes = new byte[3];

        int bytesRead;
        int n;
        for(bytesRead = 0; bytesRead < bytes.length; bytesRead += n) {
            n = pushbackInputStream.read(bytes, bytesRead, bytes.length - bytesRead);
            if (n <= 0) {
                break;
            }
        }

        if (bytesRead > 0 && !this.isByteOrderMark(bytes)) {
            pushbackInputStream.unread(bytes, 0, bytesRead);
        }

        return pushbackInputStream;
    }

    private boolean isByteOrderMark(byte[] bytes) {
        return bytes.length == 3 && bytes[0] == -17 && bytes[1] == -69 && bytes[2] == -65;
    }

    protected void postProcess(SOAPMessage soapMessage) throws SOAPException {
//      try {
//         soapMessage.writeTo(System.out);
//      }catch(Exception ex) {}
        if (!CollectionUtils.isEmpty(this.messageProperties)) {
            Iterator var2 = this.messageProperties.entrySet().iterator();

            while(var2.hasNext()) {
                Entry<String, ?> entry = (Entry)var2.next();
                soapMessage.setProperty((String)entry.getKey(), entry.getValue());
            }
        }

        if ("SOAP 1.1 Protocol".equals(this.messageFactoryProtocol)) {
            MimeHeaders headers = soapMessage.getMimeHeaders();
            if (ObjectUtils.isEmpty(headers.getHeader("SOAPAction"))) {
                headers.addHeader("SOAPAction", "\"\"");
            }
        }

    }

    public String toString() {
        StringBuilder builder = new StringBuilder("SaajSoapMessageFactory[");
        builder.append(SaajUtils.getSaajVersionString());
        if (SaajUtils.getSaajVersion() >= 2) {
            builder.append(',');
            builder.append(this.messageFactoryProtocol);
        }

        builder.append(']');
        return builder.toString();
    }
}

And i have created a Request and Response Logger which will be like below

    package com.hps.powercard;
import java.io.ByteArrayOutputStream;

import org.springframework.stereotype.Component;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.ws.soap.SoapMessage;

public class CustomEndpointInterceptor  implements EndpointInterceptor {
    @Override
    public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
        System.out.println("### SOAP REQUEST ###");
        try {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            messageContext.getRequest().writeTo(buffer);
            String payload = buffer.toString(java.nio.charset.StandardCharsets.UTF_8.name());
            System.out.println("Request "+payload);
        } catch (Exception e) {
           
        }

        return true;
    }

    @Override
    public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
        System.out.println("### SOAP RESPONSE ###");
        try {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            messageContext.getResponse().writeTo(buffer);
            String payload = buffer.toString(java.nio.charset.StandardCharsets.UTF_8.name());
            System.out.println("Response :"+payload);
        } catch (Exception e) {

        }       
        
        return true;
    }

    @Override
    public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
        System.out.println("### SOAP FAULT ###");
        try {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            messageContext.getResponse().writeTo(buffer);
            String payload = buffer.toString(java.nio.charset.StandardCharsets.UTF_8.name());
            System.out.println("SOAP FAULT "+payload);
        } catch (Exception e) {

        }
        return true;
    }

    @Override
    public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) throws Exception {
    }
}

    

I came up with this solution, which also works in my app for the SOAP reply:我想出了这个解决方案,它在我的应用程序中也适用于 SOAP 回复:

  @Bean
  public SaajSoapMessageFactory messageFactory() throws SOAPException {
    MessageFactory messageFactorySoap11 =
        MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
    MessageFactory messageFactorySoap12 =
        MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
    ThreadLocal<MessageFactory> appropriateMessageFactory = new ThreadLocal<>();
    MessageFactory messageFactoryWrapper =
        new MessageFactory() {
          @Override
          public SOAPMessage createMessage() throws SOAPException {
            return appropriateMessageFactory.get().createMessage();
          }

          @Override
          public SOAPMessage createMessage(MimeHeaders headers, InputStream in)
              throws IOException, SOAPException {
            String[] header = headers.getHeader(HttpHeaders.CONTENT_TYPE);
            boolean isSoap12 =
                (header != null
                    && header[0] != null
                    && StringUtils.lowerCase(header[0]).startsWith("application/soap+xml"));
            appropriateMessageFactory.set(isSoap12 ? messageFactorySoap12 : messageFactorySoap11);
            return appropriateMessageFactory.get().createMessage(headers, in);
          }
        };
    return new SaajSoapMessageFactory(messageFactoryWrapper);
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM