Results 1 to 7 of 7

Thread: Adding Soap Header using web service outbound adapter

  1. #1

    Default 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. #2
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,840

    Default

    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

  3. #3
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    644

    Default

    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>

  4. #4

    Default

    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?

  5. #5

    Default

    Quote 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

  6. #6
    Join Date
    Mar 2011
    Posts
    12

    Default

    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>

  7. #7
    Join Date
    Mar 2011
    Posts
    12

    Default 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 at 11:49 AM. Reason: sanitizing code

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •