Announcement Announcement Module
Collapse
No announcement yet.
Sending soapheaders in response using SimpleWebServiceInboundGateway Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Sending soapheaders in response using SimpleWebServiceInboundGateway

    SimpleWebServiceInboundGateway copies the request's soap headers from SoapMessage to SI headers, but this behavior is absent while sending the response back.

    I have some diagnostic data (read as time taken by intermediate service calls as per some schema), which I want to send back in soap headers. How can I achieve this?

  • #2
    Can you please open an issue for this? We are working on a consistent approach to header-mapping (not only WS, but also HTTP, JMS, etc) for 2.0. This would definitely fit into the big picture there.

    Thanks,
    Mark

    Comment


    • #3
      Jira created:

      https://jira.springframework.org/browse/INT-1446

      Thanks

      Comment


      • #4
        I'm looking into this now, and I could really use a bit more information. I want to make sure that what I'm doing is on the right track with what you are expecting... First of all, I am considering something along the lines of the following:
        Code:
        public void fromHeaders(MessageHeaders headers, SoapHeader target) {
            if (target != null && !CollectionUtils.isEmpty(headers)) {
                for (Map.Entry<String, Object> entry : headers.entrySet()) {
                    if (entry.getValue() instanceof String) {
                        String localPart = entry.getKey();
                        if (localPart.length() > 0) {
                            QName qname = new QName(this.namespaceUri, localPart, this.prefix);
                            target.addAttribute(qname, (String) entry.getValue());
                        }
                    }
                }
            }
        }
        That means the header mapper implementation (from which the above is an excerpt) would allow for 'namespaceUri' and 'prefix' properties to be set. The keys in the MessageHeaders map from the SpringIntegration replyMessage would then be passed into SOAP Header attributes with the key as "localPart" only. As shown above, it would only apply to String-typed MessageHeaders, and most likely, to be consistent with the HTTP HeaderMapper implementation, I will update this to check against a list of header names to be mapped (or matching against a wildcard pattern). See DefaultHttpHeaderMapper for more information on how it is done there.

        Thanks,
        Mark

        Comment


        • #5
          Actually, to be even more consistent with our DefaultHttpHeaderMapper, perhaps this would be a better implementation:
          Code:
          public void setOutboundHeaderNames(String[] outboundHeaderNames) {
              this.outboundHeaderNames = (outboundHeaderNames != null) ? outboundHeaderNames : new String[0];
          }
          
          public void fromHeaders(MessageHeaders headers, SoapHeader target) {
              if (target != null && !CollectionUtils.isEmpty(headers)) {
                  for (String name : this.outboundHeaderNames) {
                      if (QNameUtils.validateQName(name)) {
                          Object value = headers.get(name);
                          if (value instanceof String) {
                              QName qname = QNameUtils.parseQNameString(name);
                              target.addAttribute(qname, (String) value);
                          }
                      }
                  }
              }
          }
          This would require being proactive in specifying the header names to be mapped. We do that for the http case with 'mapped-request-headers' and 'mapped-response-headers' attributes.

          Please let me know if either of the previous 2 implementation options would work for your use-case.

          Thanks,
          Mark

          Comment


          • #6
            Hello Mark

            Appreciate your response on this.
            From the snippet pasted, it looks like it will add attributes within the SoapHeader element itself, but won't handle adding complex subelement types.

            I will take example of my current use case, and this is the schema of the xml info, which needs to be sent in the soapheader.. And it can be sent in header only semantically, as this is not business data:
            Code:
            <?xml version="1.0" encoding="UTF-8"?>
            <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                elementFormDefault="qualified"
                targetNamespace="xxxx/V001"
                xmlns="xxxx/V001">
                <xs:element name="SLA">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="calls" type="Calls"/>
                            <xs:element name="totalTimeTaken" type="xs:string"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:complexType name="Intf">
                    <xs:attribute name="name" type="xs:string"/>
                    <xs:attribute name="duration" type="xs:string"/>
                    <xs:attribute name="ref" type="xs:string"/>
                </xs:complexType>
                <xs:complexType name="Calls">
                    <xs:sequence>
                        <xs:element maxOccurs="unbounded" minOccurs="0" name="interface" type="Intf"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:schema>
            SLA contains calls, and calls internally contain Interface names, and their name, duration, and a reference Id (sort of traceId), which is specific to each call my application makes to an external system. Since, my app is central work flow management system for a complex architecture, this is a business requirement to have the SLA info sent back in the response.

            Saying that, do you think it should be part of soapheader? If yes, I would say it should be supported by SI as well.

            p.s. Right now, I am sending this info as comments towards the soap body

            Comment


            • #7
              It might be that a use-case such as that would require implementing the HeaderMapper and then referencing that from the SI gateway configuration. For example, we would have this as a strategy interface:
              Code:
              public interface HeaderMapper<T> {
              
                  void fromHeaders(MessageHeaders headers, T target);
              
                  Map<String, ?> toHeaders(T source);
              
              }
              In this case 'T' would be SoapHeader, so the relevant method signatures would be the following:
              Code:
              void fromHeaders(MessageHeaders headers, SoapHeader target);
              
              Map<String, ?> toHeaders(SoapHeader source);
              So, could you experiment with prototyping the 'fromHeaders(..)' method there and let me know if the ability to set that strategy reference would work for you?

              Thanks,
              Mark

              Comment


              • #8
                Hello Mark
                Code:
                public interface HeaderMapper<T> {
                
                    void fromHeaders(MessageHeaders headers, T target);
                
                    Map<String, ?> toHeaders(T source);
                
                }
                This should work.

                I will still give a try, and if any issues, will report back.

                Thanks

                Comment


                • #9
                  Great. In RC1 (coming soon), you will be able to reference an instance of that via the "header-mapper" attribute for a SimpleWebServiceInboundGateway instance (i.e. as long as you're not also referencing a "marshaller").

                  Will be looking forward to your feedback in case there is anything we should consider for 2.0 Final.

                  Thanks again,
                  Mark

                  Comment

                  Working...
                  X