5

We are trying to make a SOAP callout to an API. The sample header provided by the API is as follows

<env:Header>
     <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
           <UsernameToken>
                <Username>abcdef</Username>
                <Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">*****</Password>
            </UsernameToken>
      </Security>
</env:Header>

After wsdltoapex, when I made the call out I get the following Header as a part of my request.

<env:Header>
     <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
           <UsernameToken>
                <Username>abcdef</Username>
                <Password>*****</Password>
            </UsernameToken>
      </Security>
</env:Header>

I could see that the Type attribute in the header generated by the apex class is missing.

This is the apex code in the class that constructs the Username and password tags in the XML

public class UsernameToken_element {

        public UsernameToken_element(String username, String password) {

             this.username = username;
             this.password = password;
        }

        public String username;
        public String password;
        private String[] username_type_info = new String[]{'Username','http://www.w3.org/2001/XMLSchema','string','1','1','false'};
        private String[] password_type_info = new String[]{'Password','http://www.w3.org/2001/XMLSchema','string','1','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd','true','false'};
        private String[] field_order_type_info = new String[]{'username','password'};
}

In order to include the Type attribute in the Password tag where should I include it in the Apex code? I tried adding it as another private string and also tried to include it in the password_type_info. But it was not added in the password tag.

  • AFAIK, you do not need to set values in any private variable. Appropriate XML is constructed as per the WSDL file. – Raul Jun 15 '17 at 6:26
  • Can you share the WSDL for the service in question? – Daniel Ballinger Jun 15 '17 at 9:31
  • @DanielBallinger My friend SethuramanArunachalam has sent the WSDL in a private chat to you in Chat.stackexchange. Thanks for your help! – VigneshAngappan Jun 15 '17 at 11:04
4

Looking at http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd I see

<xsd:complexType name="PasswordString">
  <xsd:annotation>
    <xsd:documentation>
      This type is used for password elements per Section 4.1.
    </xsd:documentation>
  </xsd:annotation>
  <xsd:simpleContent>
    <xsd:extension base="wsse:AttributedString">
      <xsd:attribute name="Type" type="xsd:anyURI"/>
    </xsd:extension>
  </xsd:simpleContent>
</xsd:complexType>

So they Type attribute can just be any URL.

You will likely need to use the rare and elusively documented _att_info string array to populate the Attribute. This would be a good time to pause and consider voting for Documentation for WebServiceCallout.

The open source version of WSDL2Apex includes a test case against this attribute.

From the source WSDL:

        <xs:complexType name="Angle">
            <xs:simpleContent>
                <xs:extension base="xs:double">
                    <xs:attribute name="uom" type="tns:AngularUnit" use="required"/>
                </xs:extension>
            </xs:simpleContent>
        </xs:complexType>

Corresponding test assertion.

public class wwwMapinfoComMidevServiceUnitsV1 {
    public class Angle {
        public String uom;
        private String[] uom_att_info = new String[]{'uom'};
        private String[] apex_schema_type_info = new String[]{'http://www.mapinfo.com/midev/service/units/v1','false','false'};
        private String[] field_order_type_info = new String[]{};
    }
}

So, you create a member on the class to store the actual attribute value and a memberName_att_info String array that contains the name of the attribute.

public class UsernameToken_element {

    public UsernameToken_element(String username, String password) {

        this.username = username;
        passwordToken = new password_element(password);
        system.debug('passwordTokennnn '+passwordToken);
    }

    public String username;
    public password_element passwordToken;        
    private String[] username_type_info = new String[]{'Username','http://www.w3.org/2001/XMLSchema','string','1','1','false'};
    private String[] passwordToken_type_info = new String[]{'Password','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText','string','1','1','false'};
    private String[] apex_schema_type_info = new String[]{'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd','true','false'};
    private String[] field_order_type_info = new String[]{'username','passwordToken'};
}

public class password_element{
    public password_element( String password) {
        system.debug('passworddddd '+password);
        this.password = password;
        type = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText';             
    }


    public String password;
    public string type; // Set to 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'
    public String[] type_att_info = new String[]{'Type'};        
    private String[] password_type_info = new String[]{'Password','http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText','string','1','1','false'};
    private String[] apex_schema_type_info = new String[]{'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd','true','false'};
    private String[] field_order_type_info = new String[]{'password'};
}

Give that a try, it might work. I say might as I made a note in my version of Wsdl2Apex that

"Simple Content Types with Attributes are not supported by WebServiceCallout.invoke"

  • Thanks for the answer ! It really helped us a lot. Adding att_info after declaring the type under usernameToken_element add the Type attribute to the Username Token tag in the Header. We changed it a bit and now brought the attribute to Password tag. – VigneshAngappan Jun 20 '17 at 5:39
  • @VigneshAngappan Can you do an edit on the answer to clarify the final approach. It may be helpful to those in the future who need to solve a similar problem. – Daniel Ballinger Jun 20 '17 at 8:10
  • @VigneshAngappan Can you please post your code updates ? – CodeNinja May 6 at 12:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.