Spring boot - Server did not recognize the value of HTTP Header SOAPAction

折月煮酒 提交于 2020-04-17 20:04:47

问题


I want to consume soap service using jaxb. The generated request from jaxb is

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
      <ns2:Add xmlns:ns2="http://tempuri.org/">
         <ns2:intA>10</ns2:intA><ns2:intB>20</ns2:intB>
      </ns2:Add>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

But the response is a soap exception as stated in the title.

Caused by: org.springframework.ws.soap.client.SoapFaultClientException: System.Web.Services.Protocols.SoapException: Server did not recognize the value of HTTP Header SOAPAction: .
   at System.Web.Services.Protocols.Soap11ServerProtocolHelper.RouteRequest()
   at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message)
   at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
   at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)

Below is my soap config code. Source example: https://howtodoinjava.com/spring-boot/spring-soap-client-webservicetemplate/

    public class ConsumeSoapApplication {
            public static String wsdlurl = "http://www.dneonline.com/calculator.asmx?wsdl";
            public static void main(String[] args) {
                try {
                    JAXBContext.newInstance(com.dxc.service.soap.service.calc.ObjectFactory.class.getPackage().getName(),
                            com.dxc.service.soap.service.calc.ObjectFactory.class.getClassLoader());
                } catch (JAXBException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                SpringApplication.run(ConsumeSoapApplication.class, args);
            }

            @Bean
            CommandLineRunner lookup(SoapConnector soapConnector) {
                return args -> {
                    Integer a = 10;
                    Integer b = 20;
                    if(args.length>0){
                        a = Integer.parseInt(args[0]);
                        b = Integer.parseInt(args[1]);
                    }

                    Add add = new Add();
                    add.setIntA(a);
                    add.setIntB(b);
                    AddResponse addRes = (AddResponse) soapConnector.callWebService(wsdlurl, add);
                    System.out.println("Got Response As below ========= : ");
                    System.out.println("Added result : "+addRes.getAddResult());
                };
            }
        }

@Configuration
public class SoapConfig {    
    @Bean
        public Jaxb2Marshaller marshaller() {
            try {
                JAXBContext jb = JAXBContext.newInstance(com.dxc.service.soap.service.calc.ObjectFactory.class.getPackage().getName(),
                        com.dxc.service.soap.service.calc.ObjectFactory.class.getClassLoader());
                //Jaxb2Marshaller marshaller = (Jaxb2Marshaller) jb.createMarshaller();
                Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
                marshaller.setPackagesToScan("com.dxc.service.soap.service.calc");
                //marshaller.setContextPath("com.dxc.service.soap.calc");
                return marshaller;
            } catch (JAXBException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }   
            return null;
        }

        @Bean
        public SoapConnector soapConnector(Jaxb2Marshaller marshaller) {
            SoapConnector client = new SoapConnector();
            client.setDefaultUri("http://www.dneonline.com/calculator.asmx");
            client.setMarshaller(marshaller);
            client.setUnmarshaller(marshaller);
            return client;
        }

Please help me. Thanks.


回答1:


The issue you're facing is that the web service at http://www.dneonline.com/calculator.asmx expects a SOAPAction header. And since you're not providing one the service have no idea how to route the request.

The tutorial you're following doesn't require the SOAPAction header to do the routing.

If you take a look at how the Add operation is specified in the the WSDL, you'll find the expected value of the SOAPAction header there. Same for all the other operations the service provides.

<wsdl:operation name="Add">                                                           
  <soap:operation soapAction="http://tempuri.org/Add" style="document" />             
  <wsdl:input>                                                                        
    <soap:body use="literal" />                                                       
  </wsdl:input>                                                                       
  <wsdl:output>                                                                       
    <soap:body use="literal" />                                                       
  </wsdl:output>                                                                      
</wsdl:operation>

Assuming that your SoapConnector class is identical to the one in the tutorial you can remove the String url as input to the callWebservice method since that is already set via the client.setDefaultUri("http://www.dneonline.com/calculator.asmx"); in the SoapConnector bean. Instead, add String soapAction as an input parameter, giving you the following

public class SOAPConnector extends WebServiceGatewaySupport {

    public Object callWebService(Object request, String soapAction){
        return getWebServiceTemplate().marshalSendAndReceive(url, new SoapActionCallback(soapAction));
    }
}

Then, remove the wsdlurl as input to soapConnector.callWebService (it was wrong anyway) and add the soapHeader value for the operation you want to use instead, leaving you with this

@Bean
CommandLineRunner lookup(SoapConnector soapConnector) {
    return args -> {
        Integer a = 10;
        Integer b = 20;
        if(args.length>0){
            a = Integer.parseInt(args[0]);
            b = Integer.parseInt(args[1]);
        }

        Add add = new Add();
        add.setIntA(a);
        add.setIntB(b);
        AddResponse addRes = (AddResponse) soapConnector.callWebService(add, "http://tempuri.org/Add");
        System.out.println("Got Response As below ========= : ");
        System.out.println("Added result : "+addRes.getAddResult());
    };
}

Of course, if you want to use other operations besides Add you'll have to tweak this solution to make it generic.



来源:https://stackoverflow.com/questions/56347209/spring-boot-server-did-not-recognize-the-value-of-http-header-soapaction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!