无效的内容类型:application/xml,Soap 服务器响应 HTTP 500 错误

Invalid Content-Type:application/xml, Soap Server responding with HTTP 500 error

我已经根据客户的请求创建了一个 Soap 端点,该端点当前使用 Content-Type:text/xml。但是客户端希望将 Content-Type 作为 application/xml 发送。我不能要求客户端更改他们的内容类型,我必须修复我的服务器端点以根据使用 Spring 引导的客户端工作。请帮助并让我知道,如何修复端点以便它可以接受 application/xml。提前致谢。下面是我的堆栈跟踪:

[2021-08-23 12:38:40,255] ERROR [c.s.x.m.s.soap] SAAJ0537: Invalid Content-Type. Could be an error message instead of a SOAP message
[2021-08-23 12:38:40,264] ERROR [o.s.b.w.s.s.ErrorPageFilter] Forwarding to error page from request [/v1/serverEndpoint] due to exception [Could not create message from InputStream: Invalid Content-Type:application/xml. Is this an error message instead of a SOAP response?; nested exception is com.sun.xml.messaging.saaj.SOAPExceptionImpl: Invalid Content-Type:application/xml. Is this an error message instead of a SOAP response?]
org.springframework.ws.soap.SoapMessageCreationException: Could not create message from InputStream: Invalid Content-Type:application/xml. Is this an error message instead of a SOAP response?; nested exception is com.sun.xml.messaging.saaj.SOAPExceptionImpl: Invalid Content-Type:application/xml. Is this an error message instead of a SOAP response?
    at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:218) ~[spring-ws-core-3.0.7.RELEASE.jar:?]
    at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:62) ~[spring-ws-core-3.0.7.RELEASE.jar:?]
    at org.springframework.ws.transport.AbstractWebServiceConnection.receive(AbstractWebServiceConnection.java:92) ~[spring-ws-core-3.0.7.RELEASE.jar:?]
    at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:87) ~[spring-ws-core-3.0.7.RELEASE.jar:?]
    at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:61) ~[spring-ws-core-3.0.7.RELEASE.jar:?]
    at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:293) ~[spring-ws-core-3.0.7.RELEASE.jar:?]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) ~[servlet-api.jar:?]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[servlet-api.jar:?]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[catalina.jar:8.5.53]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.53]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-websocket.jar:8.5.53]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.53]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.53]
    at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:88) ~[spring-boot-actuator-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.53]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.53]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.53]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.53]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.53]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.53]
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) ~[spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[catalina.jar:8.5.53]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[catalina.jar:8.5.53]
    at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:128) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.boot.web.servlet.support.ErrorPageFilter.access[=11=]0(ErrorPageFilter.java:66) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilterInternal(ErrorPageFilter.java:103) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) [spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:121) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:8.5.53]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:8.5.53]
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114) [spring-boot-actuator-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104) [spring-boot-actuator-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) [spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [catalina.jar:8.5.53]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [catalina.jar:8.5.53]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109) [spring-web-5.1.8.RELEASE.jar:5.1.8.RELEASE]

Caused by: com.sun.xml.messaging.saaj.SOAPExceptionImpl: Invalid Content-Type:application/xml. Is this an error message instead of a SOAP response?
at com.sun.xml.messaging.saaj.soap.MessageImpl.identifyContentType(MessageImpl.java:740) ~[saaj-impl-1.5.0.jar:?]
at com.sun.xml.messaging.saaj.soap.MessageImpl.<init>(MessageImpl.java:331) ~[saaj-impl-1.5.0.jar:?]
at com.sun.xml.messaging.saaj.soap.ver1_2.Message1_2Impl.<init>(Message1_2Impl.java:74) ~[saaj-impl-1.5.0.jar:?]
at com.sun.xml.messaging.saaj.soap.ver1_2.SOAPMessageFactory1_2Impl.createMessage(SOAPMessageFactory1_2Impl.java:81) ~[saaj-impl-1.5.0.jar:?]
at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java:190) ~[spring-ws-core-3.0.7.RELEASE.jar:?]

端点代码:

@Endpoint
    public class RequestEndpoint {
    
        @PayloadRoot(namespace = "http://www.networks.com/RoR", localPart = "Submit")
        @ResponsePayload
        public SResponse handleRequest(@RequestPayload Submitrequest) throws URISyntaxException, IOException {
    
        SResponse sResponse = new SResponse();
            sResponse.setCommandStatus("0");
            return sResponse;
        }

由于我无法控制客户端发送的 header,因此我创建了一个解决方法。我为 SaajSoapMessageFactory 创建了一个 bean 并传递了一个 CustomSOAPMessageFactoryImpl,它实际上验证了“content-type”header。在 CustomSOAPMessageFactoryImpl 中,我覆盖了一个验证 header 的方法。这里有一个 if 条件,如果值为空或“application/xml”,则 add/updates content-type header 的值分别为 text/xml。这个解决方案对我来说很好用。

@Bean
public SaajSoapMessageFactory messageFactory() {
    SaajSoapMessageFactory saajSoapMessageFactory = new SaajSoapMessageFactory();
    saajSoapMessageFactory.setMessageFactory(new CustomSOAPMessageFactoryImpl());
    return saajSoapMessageFactory;
}

下面是 CustomSOAPMessageFactoryImpl:

import java.io.IOException;
import java.io.InputStream;

import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPMessage;

import org.apache.http.entity.ContentType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.sun.xml.messaging.saaj.SOAPExceptionImpl;
import com.sun.xml.messaging.saaj.soap.MessageImpl;
import com.sun.xml.messaging.saaj.soap.ver1_1.Message1_1Impl;
import com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl;

public class CustomSOAPMessageFactoryImpl extends SOAPMessageFactory1_1Impl{

    private static final Logger logger = LogManager.getLogger(CustomSOAPMessageFactoryImpl.class);

    @Override
    public SOAPMessage createMessage(MimeHeaders headers, InputStream in) throws IOException, SOAPExceptionImpl {

        if (headers == null) {
            headers = new MimeHeaders();
        }
        //The OR condition is a work around for Client, if they are not sending text/xml
         if (getContentType(headers) == null ||  ContentType.APPLICATION_XML.getMimeType().equals(getContentType(headers))) {
             logger.info("Received Content-Type Header Value as {}, setting it as {}", getContentType(headers), SOAPConstants.SOAP_1_1_CONTENT_TYPE);
             headers.setHeader("Content-Type", SOAPConstants.SOAP_1_1_CONTENT_TYPE);
         }

        MessageImpl msg = new Message1_1Impl(headers, in);
        msg.setLazyAttachments(lazyAttachments);
        return msg;
    }
}