【问题标题】:SoapFaultClientException : Failed to find headerSoapFaultClientException:找不到标头
【发布时间】:2021-03-19 19:03:08
【问题描述】:

一个SOAP网络服务,接受以下格式的请求 -

<?xml version = "1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV = "http://www.w3.org/2001/12/soap-envelope"
                   xmlns:ns="http://...." xmlns:ns1="http://...." xmlns:ns2="http://...."
                   xmlns:ns3="http://....">
    <SOAP-ENV:Header>
        <ns:EMContext>
            <messageId>1</messageId>
            <refToMessageId>ABC123</refToMessageId>
            <session>
                <sessionId>3</sessionId>
                <sessionSequenceNumber>2021-02-24T00:00:00.000+5:00</sessionSequenceNumber>
            </session>
            <invokerRef>CRS</invokerRef>
        </ns:EMContext>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ns1:getEmployee>
            <ns:empId>111</ns:empId>
        </ns1:getEmployee>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

当尝试使用 JAXB2 向它发出 SOAP 请求时,它给出了org.springframework.ws.soap.client.SoapFaultClientException: EMContext Header is missing

我正在使用

pring-boot-starter

spring-boot-starter-web-services

org.jvnet.jaxb2.maven2:maven-jaxb2-plugin:0.14.0

客户 -

public class MyClient extends WebServiceGatewaySupport {


    public GetEmployeeResponse getEmployee(String url, Object request){

        GetEmployeeResponse res = (GetEmployeeResponse) getWebServiceTemplate().marshalSendAndReceive(url, request);
        return res;
    }
}

配置-

@Configuration
public class EmpConfig {

    @Bean
    public Jaxb2Marshaller marshaller(){
        Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
        jaxb2Marshaller.setContextPath("com.crsardar.java.soap.client.request");
        return jaxb2Marshaller;
    }

    @Bean
    public MyClient getClient(Jaxb2Marshaller jaxb2Marshaller){
        MyClient myClient = new MyClient();
        myClient.setDefaultUri("http://localhost:8080/ws");
        myClient.setMarshaller(jaxb2Marshaller);
        myClient.setUnmarshaller(jaxb2Marshaller);
        return myClient;
    }
}

应用程序-

@SpringBootApplication
public class App {

    public static void main(String[] args) {

        SpringApplication.run(App.class, args);
    }

    @Bean
    CommandLineRunner lookup(MyClient myClient){

        return args -> {

            GetEmployeeRequest getEmployeeRequest = new GetEmployeeRequest();
            getEmployeeRequest.setId(1);
            GetEmployeeResponse employee = myClient.getEmployee("http://localhost:8080/ws", getEmployeeRequest);
            System.out.println("Response = " + employee.getEmployeeDetails().getName());
        };
    }
}

如何将 EMContext Header 添加到 SOAP 请求中?

【问题讨论】:

  • 您是通过soapui 拨打电话吗?从哪里获得请求 sn-p 是来自另一个环境吗?
  • @NirajJha 是的,它来自不同的环境。这是一个非常古老且非常大的项目,WSDL 没有得到适当的维护。如果我在 SoapUI 中使用上述输入,我会得到正确的结果。如果我使用 java.net.HttpURLConnection 并将完整的输入(带有标题,如上所述)作为字节写入 OutputStream 并从 InputStream 读取(取自 java.net.HttpURLConnection),那么也会得到正确的响应。尝试使用 JAXB2 复制相同的东西,这会给出“EMContext Header is missing”
  • 由 JAXB2 生成的类,使用 WSDL,没有任何称为 EMContext 的东西,也没有任何类上的 EMContext 的 getter 或 setter。正如我所提到的 - 这是一个非常古老且非常大的项目,WSDL 维护不正确。

标签: java spring spring-boot jaxb maven-jaxb2-plugin


【解决方案1】:

服务器正在抱怨,因为您的 Web 服务客户端没有在您的 SOAP 消息中发送 EMContext SOAP 标头。

不幸的是,目前 Spring Web Services 缺乏对包含 SOAP 标头的支持,例如,使用 JAXB 处理 SOAP 主体信息的方式类似。

作为一种解决方法,您可以使用WebServiceMessageCallback。来自docs

为了适应消息上的 SOAP 标头和其他设置的设置,WebServiceMessageCallback 接口允许您在创建消息之后访问消息,但之前它是已发送。

在你的情况下,你可以使用类似的东西:

public class MyClient extends WebServiceGatewaySupport {


  public GetEmployeeResponse getEmployee(String url, Object request){

    // Obtain the required information
    String messageId = "1";
    String refToMessageId = "ABC123";
    String sessionId = "3";
    String sessionSequenceNumber = "2021-02-24T00:00:00.000+5:00";
    String invokerRef = "CRS";

    GetEmployeeResponse res = (GetEmployeeResponse) this.getWebServiceTemplate().marshalSendAndReceive(url, request, new WebServiceMessageCallback() {

      @Override
      public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
        // Include the SOAP header content for EMContext
        try {
          SoapMessage soapMessage = (SoapMessage)message;
          SoapHeader header = soapMessage.getSoapHeader();
          StringSource headerSource = new StringSource(
            "<EMContext xmlns:ns=\"http://....\">" +
              "<messageId>" + messageId + "</messageId>" +
              "<refToMessageId>" + refToMessageId + "</refToMessageId>" +
              "<session>" +
                "<sessionId>" + sessionId + "</sessionId>" +
                "<sessionSequenceNumber>" + sessionSequenceNumber + "</sessionSequenceNumber>" +
              "</session>" +
              "<invokerRef>" + invokerRef + "</invokerRef>" +
            "</EMContext>"
          );

          Transformer transformer = TransformerFactory.newInstance().newTransformer();
          transformer.transform(headerSource, header.getResult());
        } catch (Exception e) {
          // handle the exception as appropriate
          e.printStackTrace();
        }
      }
    });
    return res;
  }
}

类似的问题已在 SO 中发布。考虑例如评论thisthis other

【讨论】:

  • 感谢您的反馈。很奇怪,@CRSardar,它应该有效。请问,你能验证消息是否真的包含标题吗?为此,在application.properties 文件中包含以下配置就足够了:logging.level.org.springframework.ws.client.MessageTracing.sent=DEBUG。拜托,你能试试看是怎么回事吗?另外,如果你调试doWithMessage方法里面的代码,一切都执行正确了吗?
  • @jccampanero 感谢您的快速回复。我使用 ObjectFactory 的方法以其他方式添加了 Headers。现在我在 WebServiceTemplate.doSendAndReceive() 处得到 NullPointerException 使用 logging.level.org.springframework.ws.client.MessageTracing.sent=DEBUG 和 logging.level.org.springframework.ws=DEBUG 我只能看到发送请求 [SaajSoapMessage{ http://....} getEmployee] 有没有办法记录完整的 SOAP 信封?请求和响应
  • 嗨@CRSardar。我很高兴听到您设法找到包含标题的替代方法。请问,你能进一步解释一下你是怎么做到的吗?是的,请使用TRACE 代替DEBUG 级别:logging.level.org.springframework.ws.client.MessageTracing.sent=TRACE。抱歉,这应该是我在之前评论中的第一个建议。请问,你可以试试吗?
  • 对不起@CRSardar,我意识到您也要求我进行响应跟踪:请尝试logging.level.org.springframework.ws.client.MessageTracing.received=TRACE
  • 嗨@CRSardar。你能试试别的吗?解决问题有进展吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-23
  • 1970-01-01
相关资源
最近更新 更多