9 Replies Latest reply on Oct 8, 2013 10:00 AM by vic neiman

    SOAP header not set

    vic neiman Newbie

      Hi everybody,

       

      I've come across an issue where the SOAPAction header is not getting set in my outgoing SOAP messages from a Switchyard project (version 1.0.0.Final created using the tooling provided). When using soapui to generate the message (using the WSDL) the SOAPAction is header is set correctly. The Switchyard project uses JAX-WS generated code (generated from the same WSDL as soapui messages) which has the annotations in place for setting the SOAPAction header, however it seems these are being ignored.

       

      Below is an excerpt from the JAX-WS generated code for the web service:

       

      @WebService(name = "wsBICISOPortType", targetNamespace = "http://tempuri.org/wsBICISO/definitions")

      @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)

      @XmlSeeAlso({

          ObjectFactory.class

      })

      public interface WsBICISOPortType {

       

       

       

       

          /**

           *

           * @param pos200

           * @return

           *     returns za.co.fnb.base24.POS210Type

           */

          @WebMethod(action = "op0200")

          @WebResult(name = "POS_210", targetNamespace = "http://tempuri.org/wsBICISO/schemas", partName = "POS_210")

          public POS210Type op0200(

              @WebParam(name = "POS_200", targetNamespace = "http://tempuri.org/wsBICISO/schemas", partName = "POS_200")

              POS200Type pos200);

      }

       

      Here is an excerpt from the valid soapui message with SOAPAction header set:

       

      POST /soap HTTP/1.1

      Accept-Encoding: gzip,deflate

      Content-Type: text/xml;charset=UTF-8

      SOAPAction: "op0200"

      User-Agent: Jakarta Commons-HttpClient/3.1

      Host: 172.18.191.200:31340

      Content-Length: 5212

       

      Here is a piece of the SOAP message sent out by the Switchyard project:

       

      POST /soap HTTP/1.1

      Content-Type: text/xml; charset=UTF-8

      Accept: */*

      SOAPAction: ""

      User-Agent: Apache CXF 2.6.6-redhat-3

      Cache-Control: no-cache

      Pragma: no-cache

      Host: 172.18.191.200:31340

      Connection: keep-alive

      Content-Length: 3855

       

      If anyone can suggest a way of getting the SOAPAction header set properly I would greatly appreciate it. I do have transformers declared in the switchyard.xml and I am not sure if this is the cause of the header not getting set, the transformers look like this:

       

      <transforms  xmlns:transform="urn:switchyard-config:transform:1.0">

          <transform:transform.jaxb from="java:za.co.fnb.base24.POS200Type" to="{http://tempuri.org/wsBICISO/schemas}POS_200"/>

          <transform:transform.jaxb from="{http://tempuri.org/wsBICISO/schemas}POS_210" to="java:za.co.fnb.base24.POS210Type"/>

       

        <transform:transform.jaxb from="java:za.co.fnb.base24.POS220Type" to="{http://tempuri.org/wsBICISO/schemas}POS_220"/>

          <transform:transform.jaxb from="{http://tempuri.org/wsBICISO/schemas}POS_220" to="java:za.co.fnb.base24.POS220Type"/>

       

        <transform:transform.jaxb from="java:za.co.fnb.base24.POS420Type" to="{http://tempuri.org/wsBICISO/schemas}POS_420"/>

          <transform:transform.jaxb from="{http://tempuri.org/wsBICISO/schemas}POS_420" to="java:za.co.fnb.base24.POS420Type"/>

        </transforms>

       

      Regards

      Victor

        • 1. Re: SOAP header not set
          Magesh Bojan Master

          Hi Victor,

           

          Please see this post here: Re: soap gw reference with basic authentication

           

          You will need to include the SOAPAction header in the config. Give a try and let us know.

           

          Magesh

          • 2. Re: SOAP header not set
            vic neiman Newbie

            Hi Magesh,

             

            thanks for the speedy reply! If I could get a pointer as to what the soap:contextMapper element should look like that'd really help. I've tried the following (using this as a reference: Message Composition - SwitchYard - Project Documentation Editor)

             

            <soap:contextMapper includes=".*" soapHeadersType="VALUE"/>

             

            and

             

            <soap:contextMapper includes="SOAPAction" soapHeadersType="VALUE"/>

             

            However, these don't have any impact.

             

            whereas initially I had this:

            <soap:contextMapper/>

             

            Thanks

            Vic

            • 3. Re: Re: SOAP header not set
              Magesh Bojan Master

              Try this one:

              <soap:contextMapper includes="SOAPAction" includeNamespaces=".*" soapHeadersType="VALUE"/>
              

               

              If it still does not work, please post a simple sample for us to help you out.

              • 4. Re: SOAP header not set
                vic neiman Newbie

                Still no go. I am going to put a sample together, however, it is not trivial as the project is rather big and has a lot of dependencies. If there is anything else I can try in the mean time please let me know.

                • 5. Re: Re: Re: SOAP header not set
                  vic neiman Newbie

                  Hi Magesh,

                   

                  I have modified the OrderService quickstart to replicate the behavior we are seeing. It does not replicate exactly what we are experienceing but what is happening is that changing the WebMethod annotation to say 'testTHIS' for the SOAP action has no effect on the SOAP header (in the InventoryServicePortType class), it still comes through as SOAPAction: "lookupItem" as you can see from the trace below.

                   

                  POST /inventory/InventoryService HTTP/1.1

                  Content-Type: text/xml; charset=UTF-8

                  Accept: */*

                  SOAPAction: "lookupItem"

                  User-Agent: Apache CXF 2.6.6-redhat-3

                  Cache-Control: no-cache

                  Pragma: no-cache

                  Host: 10.202.15.39:8080

                  Connection: keep-alive

                  Content-Length: 255


                  I have tried using both of these contextMappers in switchyard.xml 

                  <soap:contextMapper includes="SOAPAction" includeNamespaces=".*" soapHeadersType="VALUE"/>

                  and

                  <soap:contextMapper includes="SOAPAction" soapHeadersType="VALUE" includeNamespaces="http://schemas.xmlsoap.org/wsdl/soap/*"/>

                  And I cannot get the SOAPAction to be set to the value I enter in the WebMethod annotation:

                  @WebMethod(action = "testTHIS")


                  Addidtionally if contextMapper looks like this, the SOAPAction header still gets set to a value. I would have expected the header to be missing entirely from the message:

                  <soap:contextMapper/>

                  So my original problem was that I cannot get SOAPAction to be set to anything but the emptry string "" in my outgoing SOAP messages. Now we are seeing that we cannot change what is being set in that header via changing annotations.

                  • 6. Re: Re: Re: SOAP header not set
                    vic neiman Newbie

                    Would it be possible to add the SOAPAction header via a Message Composer (https://docs.jboss.org/author/display/SWITCHYARD10/Message+Composition)?

                    • 7. Re: Re: Re: SOAP header not set
                      vic neiman Newbie

                      We have had some success in setting the SOAPAction header using the XmlRootElement annotation on the Java Object that represents the specific message type we are sending, unfortunately this also affects the message body and the web service does not accept the message as the message type element is replace with the same string SOAPAction is set to.

                       

                      So the SOAPAction is correct:

                      POST /soap HTTP/1.1

                       

                       

                      Content-Type: text/xml; charset=UTF-8

                       

                       

                      Accept: */*

                       

                       

                      SOAPAction: "op0200"

                       

                       

                      User-Agent: Apache CXF 2.6.6-redhat-3

                       

                       

                      Cache-Control: no-cache

                       

                       

                      Pragma: no-cache

                       

                       

                      Host: 172.18.191.200:31340

                       

                       

                      Connection: keep-alive

                       

                       

                      Content-Length: 3794

                       

                      But the message body is wrong:

                      <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header/><SOAP-ENV:Body>

                      <op0200 xmlns="http://tempuri.org/wsBICISO/schemas">

                          <STRT_OF_TXT>ISO</STRT_OF_TXT>

                          <PROD_ID>02</PROD_ID>

                          <REL_NUM>50</REL_NUM>

                      ........................................................

                      ........................................................

                      </op0200></SOAP-ENV:Body></SOAP-ENV:Envelope>

                       

                      The op0200 element in the message body above causes the error. Unfortunately the only way we can seem to manipulate the SOAPAction header is through the XmlRootElement for the specific message POJO we are sending, this is obviously not the correct way to go about it but so far it is the only thing that gets us close to a solution.

                       

                      I had an idea of using a transformer in order to set the XML tag in the body to the correct thing, however, the transformer adds a HEX character ('ff9') to my SOAP message for some reason that also  makes the message fail on send.

                       

                      Attached is the transformer code as well as the message that is generated using it.

                      • 8. Re: Re: Re: Re: SOAP header not set
                        Keith Babo Master

                        You are likely hitting this issue with the outbound call:

                        https://issues.jboss.org/browse/SWITCHYARD-1731

                         

                        Even if the regex matches the context property you want to use as a SOAP Header, the fact that it doesn't have an EndpointLabel of HTTP is causing it to get screened out.  A fix will be available in 1.1.  For now, you need a custom context mapper on your reference binding that looks something like this:

                         

                        import org.switchyard.Context;
                        import org.switchyard.Property;
                        import org.switchyard.component.soap.composer.SOAPBindingData;
                        import org.switchyard.component.soap.composer.SOAPContextMapper;
                        
                        
                        public class SOAPActionMapper extends SOAPContextMapper {
                        
                        
                          @Override
                          public void mapTo(Context context, SOAPBindingData soapData) throws Exception {
                            // delegate to parent to pick up existing context mapping logic for SOAP
                            super.mapTo(context, restData);
                        
                            // pick up the context property associated with SOAPAction
                            Property soapAction = context.getProperty("SOAPAction");
                        
                            // if the property exists, set it on the SOAPMessage MIME headers
                            if (soapAction != null) {
                              soapData.getSOAPMessage().getMimeHeaders().addHeader("SOAPAction", (String)soapAction.getValue());
                            }
                          }
                        }
                        
                        
                        

                         

                        One thing that's important to point out here is that this assumes the SOAPAction context property is present on the exchange in the first place.  In the example app you posted, the SOAPAction header will be present on the inbound exchange as a context property, but will not be present on the invocation outbound from the bean service.  This is due to a limitation in bean services in SY 1.0 where context properties cannot be set from a bean service on references.  This will also be addressed in 1.1.  In the meantime, you can use a Camel route in place of your bean service to set the header.

                         

                        hth,

                        keith

                        • 9. Re: Re: Re: Re: Re: SOAP header not set
                          vic neiman Newbie

                          Thanks, I tried that however it did not work for me. What did work in the end is implementing my own Java transformers for each message described in the web service, but more so including the namespace attribute in the first element of each field caused the SOAPAction header to be set to the expected value. I experimented with both and transformers that look like this are the ones that worked for me:

                           

                          builder.append("<POS_200 xmlns=\"http://tempuri.org/wsBICISO/schemas\">"+

                                    "<STRT_OF_TXT>"+from.getSTRTOFTXT()+"</STRT_OF_TXT>"+

                                    "<PROD_ID>"+from.getPRODID()+"</PROD_ID>"+

                                    "<REL_NUM>"+from.getRELNUM()+"</REL_NUM>"+

                          .........

                          ......

                          ....

                          builder.append("</POS_200>");

                           

                          Transformers that look like this do  not:

                           

                          builder.append("<POS_200>")

                          .......

                          ....

                          builder.append("</POS_200>")

                           

                          So the namespace attribute solved my problems, pretty sure there are plenty of other, better ways (the transformers were very long as the messages contain lots of XML fields) but I was pressed for time to provide a solution.

                           

                          Regards and thanks

                          Vic