SoapFaultClientException : Failed to find header

Viewed 292

A SOAP Web-service, which accepts request in following format -

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

When trying to make a SOAP request to it using JAXB2, it is giving org.springframework.ws.soap.client.SoapFaultClientException: EMContext Header is missing

I am using

pring-boot-starter

spring-boot-starter-web-services

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

and

Client -

public class MyClient extends WebServiceGatewaySupport {


    public GetEmployeeResponse getEmployee(String url, Object request){

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

Configuration -

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

App -

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

How can I add EMContext Header to the SOAP request?

1 Answers

The server is complaining because your Web Service client is not sending the EMContext SOAP header in your SOAP message.

Unfortunately, currently Spring Web Services lack of support for including SOAP headers in a similar way as the SOAP body information is processed using JAXB, for example.

As a workaround, you can use WebServiceMessageCallback. From the docs:

To accommodate the setting of SOAP headers and other settings on the message, the WebServiceMessageCallback interface gives you access to the message after it has been created, but before it is sent.

In your case, you can use something like:

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

Similar questions have been posted in SO. Consider for instance review this or this other.

Related