Announcement Announcement Module
Collapse
No announcement yet.
Adding Soap Header using web service outbound adapter Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Adding Soap Header using web service outbound adapter

    I was wondering if there's any way of adding a custom soap header before invoking a webservice using spring integration webservice outbound adapter.

    Currently I am in design stage so want iron out challenges before moving to development/POC. Here is what I am trying to achieve :

    I will be getting Spring Integration's Message from a channel. A chain of Message Handlers will work on this message which contains:

    1.) A message transformer : transforms the message to the required Jaxb objects generated using contract xsd's.
    2.) Webservice outbound gateway: which should invoke the webservice and send the reply to another reply channel

    The catch is that I want to add a custom soap header expected by webservice before invoking it. I can add header enricher between two steps defined above but I am not sure whether they will transform into SOAP Header.

    Kindly advice.

    Regards,
    Sukhi

  • #2
    Your use case might provide some valuable feedback for this issue:
    https://jira.springsource.org/browse/INT-1532
    (please vote for it, and you can add a watch as well)

    However, it might be simpler than that. Can you describe in a bit more detail what type of information you want to add as a SOAP header? Specifically, is the value determined at runtime based on Message content?

    Thanks,
    Mark

    Comment


    • #3
      Hello.
      You can do it with request-callback and implementation like this:
      Code:
      public class MyWebServiceMessageCallback implements WebServiceMessageCallback {
      
          private Transformer transformer;
      
          private String authHeader;
      
          public void setAuthHeader(String authHeader) {
              this.authHeader = authHeader;
          }
      
          public void setTransformer(Transformer transformer) {
              this.transformer = transformer;
          }
      
          public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
              SoapHeader soapHeader = ((SoapMessage) message).getSoapHeader();
              transformer.transform(new StringSource(authHeader), soapHeader.getResult());
          }
      }
      Where the authHeader is a simple XML-element like this:
      HTML Code:
      <AuthHeader>
               <Username>TEST</Username>
               <Password>TEST</Password>
            </AuthHeader>

      Comment


      • #4
        Thanks Cleric for the input..... I may have to try it out... but I am not sure how this approach would work if I need to provide a Jaxb object to be marshalled at runtime and to be used as SOAP header.... but this will definitely give me pointer to find out my way.

        Mark,
        Thanks for the prompt reply..... Frankly I am unaware about HeaderMapper.... but I can certainly share my use case in detail as it is just a POC. Here is it:

        following payload will be received on a channel:

        <tns:HolidayEnquiry xmlns:tns="http://www.example.org/HotelEnquirySystem"
        xmlns:tns1="http://www.example.org/base" xmlns:tns2="http://www.example.org/Travel"
        xmlns: xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi: schemaLocation="http://www.example.org/HotelEnquirySystem HotelEnquirySystem.xsd ">
        <tns1:CustomerName>XXX</tns1:CustomerName>
        <tns1:CustomerAddress>XXXX</tns1:CustomerAddress>
        <tns1:CustomerMobile>XXXXXX</tns1:CustomerMobile>
        <tns1:CustomerEmail>XXXXX</tns1:CustomerEmail>
        <tns1: Destination>XXXX</tns1: Destination>
        <tns1:Budget>0.0</tns1:Budget>
        <tns: HotelEnquiry>
        <tns1: NoOfPeople>0</tns1:NoOfPeople>
        <tns1: Class>Luxury</tns1:Class>
        <tns1: CheckInDate>2001-01-01</tns1:CheckInDate>
        <tns1: CheckOutDate>2001-01-01</tns1:CheckOutDate>
        </tns: HotelEnquiry>
        <tns:TravelEnquiry>
        <tns1:Mode>Train</tns1:Mode>
        <tns1:TravelType>To</tns1:TravelType>
        <tns1:Class>Luxury</tns1:Class>
        <tns1:TravelDate>2001-01-01</tns1:TravelDate>
        <tns1:ReturnDate>2001-01-01</tns1:ReturnDate>
        <tns1:BoardingCity>tns1:BoardingCity</tns1:BoardingCity>
        </tns:TravelEnquiry>
        </tns:HolidayEnquiry>


        This should be unmarshalled to jaxb objects, some business validations should be done and then it should be sent to another channel. A filter should get message from this channel and invoke a webservice. Now the webservice to be invoked should be somewhat like this:

        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:hot="http://www.example.org/HotelFinderContract" xmlns:base="http://www.example.org/base">
        <soapenv:Header>
        <hot:CustomerHeaderType>
        <!--You may enter the following 6 items in any order-->
        <base:CustomerName>?</base:CustomerName>
        <base:CustomerAddress>?</base:CustomerAddress>
        <base:CustomerMobile>?</base:CustomerMobile>
        <base:CustomerEmail>?</base:CustomerEmail>
        <base: Destination>?</base: Destination>
        <base:Budget>?</base:Budget>
        </hot:CustomerHeaderType>
        </soapenv:Header>
        <soapenv:Body>
        <hot:HotelFinderRequest>
        <base:CheckInDate>?</base:CheckInDate>
        <base:CheckOutDate>?</base:CheckOutDate>
        <base: Destination>?</base: Destination>
        <base:NoOfPeople>?</base:NoOfPeople>
        <base:Class>?</base:Class>
        </hot:HotelFinderRequest>
        </soapenv:Body>
        </soapenv:Envelope>


        As you can see, service request requires a header which is composed of some elements from HolidayEnquiry. And few others are mapped to HotelFinderRequest in soap:body.

        Using transformer, I can transform the incoming message into CustomerHeaderType and HotelFinderRequest jaxb objects but now while invoking webservice how these objects will be marshalled to form required soap:envelope's parts.

        I was thinking of using webservice outbound adapter but could not figure out the addition of CustomerHeader.

        Can ws:header-enricher can help here?

        Comment


        • #5
          Originally posted by Mark Fisher View Post
          Your use case might provide some valuable feedback for this issue:
          https://jira.springsource.org/browse/INT-1532
          (please vote for it, and you can add a watch as well)

          However, it might be simpler than that. Can you describe in a bit more detail what type of information you want to add as a SOAP header? Specifically, is the value determined at runtime based on Message content?

          Thanks,
          Mark
          Hi Mark,

          Would appreciate your inputs.... I have added use case in the thread.

          Regards,
          Sukhi

          Comment


          • #6
            Added another use case to the JIRA issue. Any pointers to the best way to implement this before this is available out of the box?
            ================================================== ===============================================
            My use case.

            using a Marshalling WSOutbound gateway utilizing JAXB2.0 as the marshaller and SOAP1.1 message-factory. All is well until we need to pass the message with a empty SOAPHeader tag.

            I am now required to add a custom header to the message so I try to do so on the MesageBuilder interface. When I do this based on the below example, the header is not added to the outbound message.
            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Header/>
            <soapenv:Body>
            <!-- data-->
            </soapenv:Body>
            </soapenv:Envelope>

            Message<String> message1 = MessageBuilder.withPayload("test")
            .setHeader("foo", "bar")
            .build();

            Also, we need to add the header with a custom namespace. Current setHeader method signature for : "org.springframework.integration.support.MessageBu ilder<T>" has setHeader(String headerName, Object headerValue)
            Can we extend to add a custom namespace as well.

            Required SOAP XML structure:

            <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
            <soapenv:Header>
            <abc:customID xmlns:abc="http://abc.com/abc">static value</abc:traceID>
            </soapenv:Header>
            <soapenv:Body>
            <!-- Maps to the JAXB object that corresponds perfectly to the SOAP Body to Message Payload.
            </soapenv:Body>
            </soapenv:Envelope>

            Comment


            • #7
              Applying the Interceptor to ws:outbound-gateway for setting SOAP Headers

              I was able to set the required header with the static value and required namespace using the interceptor attribute on the ws:outbound-gateway.

              For reference to anyone who encounters the same issue.

              <ws:outbound-gateway id="outbndgw1" uri="http://localhost:9082/"
              request-channel="reqchannel1" marshaller="marsh1"
              unmarshaller="unmarsh1" interceptor="customInterceptor" />

              <bean id="customInterceptor" class="com.abc.xyz.interceptor.XYZMessageHeaderInt erceptor">
              </bean>

              XYZMessageHeaderInterceptor implements ClientInterceptor


              ==========

              public class XYZMessageHeaderInterceptor implements ClientInterceptor

              {

              implement the handleRequest method and set the required header.

              SoapMessage soapMessage = (SoapMessage) messageContext.getRequest();

              SoapHeader sh = soapMessage.getSoapHeader();

              SoapHeaderElement soapHeaderInformation = sh.addHeaderElement(new QName("http://abc.com", "XYZ",
              abc));


              }
              Last edited by Shirish18; Jun 3rd, 2011, 12:49 PM. Reason: sanitizing code

              Comment

              Working...
              X