Search code examples
javaspring-bootsoapcontent-type

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


I have created a Soap Endpoint based on Client's request and that endpoint currently works with Content-Type:text/xml. But Client wants to send Content-Type as application/xml. I cannot ask client to change their content-type and I have to fix my server endpoint to work according to client using Spring boot. Please help and let me know, how can I fix the endpoint so that it can accept application/xml. Thanks in advance. Below is my Stacktrace:

[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$000(ErrorPageFilter.java:66) [spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.boot.web.servlet.support.ErrorPageFilter$1.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 code:

@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;
        }

Solution

  • Since I don't have control over the header that client sends, I have created a workaround. I have created a bean for SaajSoapMessageFactory and passed a CustomSOAPMessageFactoryImpl which actually validates the "content-type" header. In CustomSOAPMessageFactoryImpl, I am overriding a method that validates the header. Here, there is an if condition which add/updates the content-type header's value as text/xml if the value is empty or "application/xml" respectively. This solution is working fine for me.

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

    Below is the 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;
        }
    }