You can generate SOAP headers for use with WebServiceCallout.invoke
using a member and a corresponding string with the _hns
suffix.
For reference, Wsdl2Apex processes this around Line 86 of the BindingClass.java file.
You will need to create an inner class to contain the header data.
Here is an example from the UPS XAV Service WSDL. The code was generated using the FuseIT SFDC Explorer Wsdl2Apex function (Disclosure, this is my current employer).
// Generated by FuseIT WSDL2Apex (http://www.fuseit.com/Solutions/SFDC-Explorer/Help-WSDL-Parser.aspx)
// Methods Included: ProcessXAV
// Primary Port Class Name: XAVPort
public class wwwUpsComWsdlXoltwsXavV10 {
public class XAVPort {
public String endpoint_x = 'https://wwwcie.ups.com/webservices/XAV';
public Map<String,String> inputHttpHeaders_x;
public Map<String,String> outputHttpHeaders_x;
public String clientCertName_x;
public String clientCert_x;
public String clientCertPasswd_x;
public Integer timeout_x;
// Setting this member will populate the <env:Header/> element
public wwwUpsComXmlschemaXoltwsUpssV10.UPSSecurity_element UPSSecurity;
private String UPSSecurity_hns = 'UPSSecurity=http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0';
private String[] ns_map_type_info = new String[]{'http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','wwwUpsComXmlschemaXoltwsUpssV10','http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0','wwwUpsComXmlschemaXoltwsCommonV10','http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1','wwwUpsComXmlschemaXoltwsErrorV11','http://www.ups.com/XMLSchema/XOLTWS/xav/v1.0','wwwUpsComXmlschemaXoltwsXavV10'};
public wwwUpsComXmlschemaXoltwsXavV10.XAVResponse_element ProcessXAV(wwwUpsComXmlschemaXoltwsCommonV10.RequestType Request,String RegionalRequestIndicator,String MaximumCandidateListSize,wwwUpsComXmlschemaXoltwsXavV10.AddressKeyFormatType AddressKeyFormat) {
// ...
}
}
}
public class wwwUpsComXmlschemaXoltwsUpssV10 {
public class UPSSecurity_element {
public wwwUpsComXmlschemaXoltwsUpssV10.UPSSecurity_UsernameToken_element UsernameToken;
public wwwUpsComXmlschemaXoltwsUpssV10.UPSSecurity_ServiceAccessToken_element ServiceAccessToken;
private String[] UsernameToken_type_info = new String[]{'UsernameToken','http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','','1','1','false'};
private String[] ServiceAccessToken_type_info = new String[]{'ServiceAccessToken','http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','','1','1','false'};
private String[] apex_schema_type_info = new String[]{'http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','true','false'};
private String[] field_order_type_info = new String[]{'UsernameToken','ServiceAccessToken'};
}
public class UPSSecurity_ServiceAccessToken_element {
public String AccessLicenseNumber;
private String[] AccessLicenseNumber_type_info = new String[]{'AccessLicenseNumber','http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','string','1','1','false'};
private String[] apex_schema_type_info = new String[]{'http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','true','false'};
private String[] field_order_type_info = new String[]{'AccessLicenseNumber'};
}
public class UPSSecurity_UsernameToken_element {
public String Username;
public String Password;
private String[] Username_type_info = new String[]{'Username','http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','string','1','1','false'};
private String[] Password_type_info = new String[]{'Password','http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','string','1','1','false'};
private String[] apex_schema_type_info = new String[]{'http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0','true','false'};
private String[] field_order_type_info = new String[]{'Username','Password'};
}
}
If you do want to go down the HttpRequest path as Keith commented, the FuseIT SFDC Explorer tool can also generate code using the HttpRequest. I cover this in my Dreamforce 2014 presentation.
Here is how I have tried using workbench to test a SOAP web service. Hope this helps.
First you have to get the session ID by passing a Soap request(I copied the request XML from SoapUI) to login method of the Salesforce SOAP API.
Service URL: /services/Soap/u/37.0
Method : Post
Request Headers: (below)
Content-Type: text/xml; charset=UTF-8
Accept: text/xml
SOAPAction: ''
Soap Request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:partner.soap.sforce.com">
<soapenv:Header>
<urn:CallOptions>
<urn:client></urn:client>
<urn:defaultNamespace></urn:defaultNamespace>
</urn:CallOptions>
<urn:LoginScopeHeader>
<urn:organizationId></urn:organizationId>
<!--Optional:-->
<urn:portalId></urn:portalId>
</urn:LoginScopeHeader>
</soapenv:Header>
<soapenv:Body>
<urn:login>
<urn:username>****************</urn:username>
<urn:password>****password+security token****</urn:password>
</urn:login>
</soapenv:Body>
</soapenv:Envelope>
Execute it you will get the webservice response.
In the response you will get the session ID. Copy it and keep it in your notepad to call your Apex webservice.
For next call you have to use the following details.
Service URL: /services/Soap/class/sarojkbera/MyWebService
(MyWebService is the Apex class exposed as Soap service)
Apex Class:
global class MyWebService {
webService static String makeContact(String firstName, String lastName) {
return 'Hello '+firstName+' ' +lastName;
}
}
Method : Post
Request Headers: (below)
Content-Type: text/xml; charset=UTF-8
Accept: text/xml
SOAPAction: ''
Soap Request:
Here I have used the generated Soap request from SoapUI.
Put the session ID (obtained in the previous step) in the request XML.
Execute it and you will get the Webservice response as below.
Best Answer
I had to modify your webservice a bit to get a valid WSDL that SOAPUI could import. When you pass the accountId as the
Account
type Salesforce adds a whole lot of extra simple and complex types to the WSDL that aren't really needed. The WSDL goes from 6 KB to 542 KB. By sticking with strings or Ids the WSDL is much simpler.Without any modifications I get the following error from SoupUI:
This is because there is no complex or simple type
address
in namespace http://soap.sforce.com/schemas/class/DFB/myClass (alias tns).Here is my simplified Apex web service:
Be sure to save the WSDL directly from the link rather than opening it in the browser and then saving it to disk. I've found browsers can make subtle changes to the WSDL that will sometimes corrupt them.
The resulting WSDL imported into SoupUI successfully for me and I was able to make the following request. Here the SessionID was pulled from an active session using the anonymous apex:
Sample request to same pod as the session was retrieved from:
Which gave the response: