【问题标题】:Spring boot - Server did not recognize the value of HTTP Header SOAPActionSpring boot - 服务器无法识别 HTTP Header SOAPAction 的值
【发布时间】:2019-05-28 17:15:50
【问题描述】:

我想使用 jaxb 使用肥皂服务。 来自 jaxb 的生成请求是

<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>

但响应是标题中所述的肥皂异常。

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)

下面是我的肥皂配置代码。来源示例: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;
        }

请帮助我。谢谢。

【问题讨论】:

    标签: spring-boot web-services soap jaxb jaxb2-maven-plugin


    【解决方案1】:

    您面临的问题是http://www.dneonline.com/calculator.asmx 的网络服务需要SOAPAction 标头。而且由于您不提供服务,因此该服务不知道如何路由请求。

    您正在学习的教程不需要 SOAPAction 标头来执行路由。

    如果您看一下Add 操作是如何在WSDL 中指定的,您会在那里找到SOAPAction 标头的预期值。该服务提供的所有其他操作都相同。

    <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>
    

    假设您的SoapConnector 类与the tutorial 中的类相同,您可以删除String url 作为callWebservice 方法的输入,因为它已经通过SoapConnector bean 中的client.setDefaultUri("http://www.dneonline.com/calculator.asmx"); 设置.相反,添加String soapAction 作为输入参数,为您提供以下内容

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

    然后,删除 wsdlurl 作为 soapConnector.callWebService 的输入(无论如何都是错误的),并为您要使用的操作添加 soapHeader 值,留下这个

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

    当然,如果您想使用除Add 之外的其他操作,则必须调整此解决方案以使其通用。

    【讨论】:

    • 完美。谢谢。你拯救了我的一天.. (‾▿‾)
    【解决方案2】:

    @Misantorp 的答案是调用必须传递操作的 SOAP Web 服务的解决方案。 我使用了相同的建议,可以调用 w3School 的温度转换器。

    [链接]https://github.com/suhelm/SPRINGBOOT/tree/main/SOAP_temparature_converter

    【讨论】:

      猜你喜欢
      • 2014-12-02
      • 2011-12-19
      • 2016-04-30
      • 2012-01-19
      • 2018-11-16
      • 1970-01-01
      • 1970-01-01
      • 2014-05-06
      • 1970-01-01
      相关资源
      最近更新 更多