function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
thecrmninjathecrmninja 

SOAP Webservice Callout - Issue Generating Output Headers/Response

I'm a self-proclaimed novice programmer, especially with Apex.  I'm working with a WSDL based webservice callout and not seeing what I would expect.  Any perspective would be appreciated.  The following sample is broken into three portions(urls, authentication redacted).  ...1.Asynchronous Callout 2.WSDL2APEX Class 3.Debug log of @future callout. 

 

 

/////////////////////////////////////////////////////Callout///////////////////////////////////////////////////// public class LeadIVAULTCallout { @future (callout=true) public static void LeadIVAULTCalloutPOST(Set <Id> leadPDFIDs) { Map<ID,Attachment> leadPDFMap = new Map<ID,Attachment>( [select attachment.ID from Attachment where id IN :leadPDFIDs] ) ; for( ID i : leadPDFIDs ){ Attachment STLeadPDF = leadPDFMap.get(i); String DocumentID = STLeadPDF.ID; String applicationId = 'GFT-CUST-99YR'; //docSample.DocSamplePort stub = new docSample.DocSamplePort(); globalforexSpringthroughComServices.SFDocumentManagementSoap stub = new globalforexSpringthroughComServices.SFDocumentManagementSoap(); stub.inputHttpHeaders_x = new Map<String, String>(); //Setting a basic authentication header stub.inputHttpHeaders_x.put('Authorization', <VALUE>); globalforexSpringthroughComServices.SFResult Stub2 = Stub.QueueDocument(DocumentID,applicationId); stub.outputHttpHeaders_x = new Map<String, String>(); String myHeader = stub.outputHttpHeaders_x.get('My-Header'); system.debug('headers: ' + stub.outputHttpHeaders_x + myHeader); } } } /////////////////////////////////////////////////////wsdl2apex///////////////////////////////////////////////////// //Generated by wsdl2apex public class globalforexSpringthroughComServices { public class SFDocumentManagementSoap { public String endpoint_x = 'http://<URLHERE>'; public Map<String,String> inputHttpHeaders_x; public Map<String,String> outputHttpHeaders_x; public String clientCert_x; public String clientCertPasswd_x; public Integer timeout_x; public globalforexSpringthroughComServices.AuthSoapHeader AuthSoapHeader; private String AuthSoapHeader_hns = 'AuthSoapHeader=http://<URLHERE>'; private String[] ns_map_type_info = new String[]{'http://<URLHERE>', 'globalforexSpringthroughComServices'}; public globalforexSpringthroughComServices.SFResult QueueDocument(String documentId,String applicationId) { globalforexSpringthroughComServices.QueueDocument_element request_x = new globalforexSpringthroughComServices.QueueDocument_element(); globalforexSpringthroughComServices.QueueDocumentResponse_element response_x; request_x.documentId = documentId; request_x.applicationId = applicationId; Map<String, globalforexSpringthroughComServices.QueueDocumentResponse_element> response_map_x = new Map<String, globalforexSpringthroughComServices.QueueDocumentResponse_element>(); response_map_x.put('response_x', response_x); WebServiceCallout.invoke( this, request_x, response_map_x, new String[]{endpoint_x, 'http://<URLHERE>', 'http://<URLHERE>', 'QueueDocument', 'http://<URLHERE>', 'QueueDocumentResponse', 'globalforexSpringthroughComServices.QueueDocumentResponse_element'} ); response_x = response_map_x.get('response_x'); return response_x.QueueDocumentResult; } } public class AuthSoapHeader { public String UserName; public String Password; private String[] UserName_type_info = new String[]{'UserName','http://www.w3.org/2001/XMLSchema','string','0','1','false'}; private String[] Password_type_info = new String[]{'Password','http://www.w3.org/2001/XMLSchema','string','0','1','false'}; private String[] apex_schema_type_info = new String[]{'http://globalforex.springthrough.com/services/','true','false'}; private String[] field_order_type_info = new String[]{'UserName','Password'}; } public class QueueDocumentResponse_element { public globalforexSpringthroughComServices.SFResult QueueDocumentResult; private String[] QueueDocumentResult_type_info = new String[]{'QueueDocumentResult','http://globalforex.springthrough.com/services/','SFResult','0','1','false'}; private String[] apex_schema_type_info = new String[]{'http://<URLHERE>','true','false'}; private String[] field_order_type_info = new String[]{'QueueDocumentResult'}; } public class QueueDocument_element { public String documentId; public String applicationId; private String[] documentId_type_info = new String[]{'documentId','http://www.w3.org/2001/XMLSchema','string','0','1','false'}; private String[] applicationId_type_info = new String[]{'applicationId','http://www.w3.org/2001/XMLSchema','string','0','1','false'}; private String[] apex_schema_type_info = new String[]{'http://<URLHERE>','true','false'}; private String[] field_order_type_info = new String[]{'documentId','applicationId'}; } public class SFResult { public Boolean success; public String returnValue; private String[] success_type_info = new String[]{'success','http://www.w3.org/2001/XMLSchema','boolean','1','1','false'}; private String[] returnValue_type_info = new String[]{'returnValue','http://www.w3.org/2001/XMLSchema','string','0','1','false'}; private String[] apex_schema_type_info = new String[]{'http://<URLHERE>','true','false'}; private String[] field_order_type_info = new String[]{'success','returnValue'}; } } /////////////////////////////////////////////////////Debug Log///////////////////////////////////////////////////// User Tom Fox Date 2/24/2010 8:18:53 PM EST Status Success Application Browser Request Type Api Operation FutureHandler Duration (ms) 282 Log Length 20100225011853.316:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 34, column 1: headers: {}null

 

 

 

 

Am I crazy to expect more from my Debug Log?  I'm fearful that I'm not properly requesting the response from the webservice.

Best Answer chosen by Admin (Salesforce Developers) 
thecrmninjathecrmninja

I wanted to share a workaround I was able to put together that SEEMS to have addressed the issue (I'm waitinf or confirmation from the vendor that constructed teh WebService).  I essentially followed a Workaround That I located in this Community Post  (You can find it in a few).   

 

Asynch Method making webservice call....

 

public class LeadCallout { @future (callout=true) public static void LeadCalloutPOST(Set <Id> leadPDFIDs) { Map<ID,Attachment> leadPDFMap = new Map<ID,Attachment>( [select attachment.ID from Attachment where id IN :leadPDFIDs] ) ; for( ID i : leadPDFIDs ){ Attachment STLeadPDF = leadPDFMap.get(i); String DocumentID = STLeadPDF.ID; String applicationId = '<VALUE REDACTED>'; String UserName = '<VALUE REDACTED>'; String Password = '<VALUE REDACTED>'; string SoapXMLBody; SoapXMLBody ='<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header> <AuthSoapHeader xmlns="<URL VALUE REDACTED>"><UserName>'+UserName+'</UserName> <Password>'+Password+'</Password></AuthSoapHeader></soap:Header><soap:Body><QueueDocument xmlns="<URL VALUE REDACTED>"><documentId>'+DocumentID+'</documentId><applicationId>'+applicationId+'</applicationId></Q ueueDocument></soap:Body></soap:Envelope>'; string SoapXML; SoapXML = SoapXMLBody; Integer ContentLength = 0; ContentLength = SoapXML.length(); Http h = new Http(); HttpRequest req = new HttpRequest(); HttpResponse res = new HttpResponse(); req.setMethod('POST'); req.setEndPoint('<URL VALUE REDACTED>'); req.setHeader('Content-type','text/xml'); req.setHeader('Content-Length',ContentLength.format()); req.setHeader('SoapAction','<URL VALUE REDACTED>'); req.setBody(SoapXML); System.Debug(req.getHeader('req.getHeader; '+'Content-Length')); System.Debug('req: '+req); System.Debug('req.getBody'+req.getBody()); res = h.send(req); System.Debug('res:'+res); String auth = res.getBody(); System.Debug('Debug(auth:'+auth); } } }

 

Debug log (not the success=true which is a boolean set as part of the WS's Document Response method)

 

20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 51, column 9: 584 20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 52, column 9: System.HttpRequest[Endpoint=<URL VALUE REDACTED>, Method=POST] 20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 53, column 9: <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header> <AuthSoapHeader xmlns="<URL VALUE REDACTED>"><UserName>VALUE REDACTED></UserName> <Password>VALUE REDACTED></Password></AuthSoapHeader></soap:Header><soap:Body><QueueDocument xmlns="<URL VALUE REDACTED>"><documentId>VALUE REDACTED></documentId><applicationId>VALUE REDACTED></applicationId></QueueDocument></soap:Body></soap:Envelope> 20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 55, column 9: System.HttpResponse[Status=OK, StatusCode=200] 20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 58, column 9: <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><QueueDocumentResponse xmlns="<URL VALUE REDACTED>"><QueueDocumentResult><success>true</success><returnValue>The operation completed normally</returnValue></QueueDocumentResult></QueueDocumentResponse></soap:Body></soap:Envelope>

 

 

 

 

 So, in essence, I posting the SOAP call as a string.  The advantage is that this allows me to debug within the future call (something the WSDL2Apex seems to have issues with, from what I saw on other posts).  The disadvantage is that I'm using a cobbled system instead of the nice shiny one that SF offers.  So, that being said, If anybody wants to weigh in my earlier attempt, please feel free.  If, like me, you find you're having troubles, you might try this approach.

Also, if anybody looks at my workaround and has a way to make it more elegant, etc., please share.

 

All Answers

SuperfellSuperfell
I think you need to remove the "stub.outputHttpHeaders_x = new Map<String, String>();" line, otherwise your log will always show nothing, as thats what you just constructed.
thecrmninjathecrmninja

Thank you for your timely response Simon.  That line had been a subsequent attempt to try to generate some sort of response.  After removing it and leaving only this portion relating to output headers....

 

 

system.debug('headers: ' + stub.outputHttpHeaders_x);

 

 I still get null back as a result of firing the class.....

 

 

20100225130124.307:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 34, column 1: headers: null

 

 In your experience, is my attempt to gather the output header well formulated or would you advocate a different approach?

 

 

thecrmninjathecrmninja

I wanted to share a workaround I was able to put together that SEEMS to have addressed the issue (I'm waitinf or confirmation from the vendor that constructed teh WebService).  I essentially followed a Workaround That I located in this Community Post  (You can find it in a few).   

 

Asynch Method making webservice call....

 

public class LeadCallout { @future (callout=true) public static void LeadCalloutPOST(Set <Id> leadPDFIDs) { Map<ID,Attachment> leadPDFMap = new Map<ID,Attachment>( [select attachment.ID from Attachment where id IN :leadPDFIDs] ) ; for( ID i : leadPDFIDs ){ Attachment STLeadPDF = leadPDFMap.get(i); String DocumentID = STLeadPDF.ID; String applicationId = '<VALUE REDACTED>'; String UserName = '<VALUE REDACTED>'; String Password = '<VALUE REDACTED>'; string SoapXMLBody; SoapXMLBody ='<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header> <AuthSoapHeader xmlns="<URL VALUE REDACTED>"><UserName>'+UserName+'</UserName> <Password>'+Password+'</Password></AuthSoapHeader></soap:Header><soap:Body><QueueDocument xmlns="<URL VALUE REDACTED>"><documentId>'+DocumentID+'</documentId><applicationId>'+applicationId+'</applicationId></Q ueueDocument></soap:Body></soap:Envelope>'; string SoapXML; SoapXML = SoapXMLBody; Integer ContentLength = 0; ContentLength = SoapXML.length(); Http h = new Http(); HttpRequest req = new HttpRequest(); HttpResponse res = new HttpResponse(); req.setMethod('POST'); req.setEndPoint('<URL VALUE REDACTED>'); req.setHeader('Content-type','text/xml'); req.setHeader('Content-Length',ContentLength.format()); req.setHeader('SoapAction','<URL VALUE REDACTED>'); req.setBody(SoapXML); System.Debug(req.getHeader('req.getHeader; '+'Content-Length')); System.Debug('req: '+req); System.Debug('req.getBody'+req.getBody()); res = h.send(req); System.Debug('res:'+res); String auth = res.getBody(); System.Debug('Debug(auth:'+auth); } } }

 

Debug log (not the success=true which is a boolean set as part of the WS's Document Response method)

 

20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 51, column 9: 584 20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 52, column 9: System.HttpRequest[Endpoint=<URL VALUE REDACTED>, Method=POST] 20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 53, column 9: <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header> <AuthSoapHeader xmlns="<URL VALUE REDACTED>"><UserName>VALUE REDACTED></UserName> <Password>VALUE REDACTED></Password></AuthSoapHeader></soap:Header><soap:Body><QueueDocument xmlns="<URL VALUE REDACTED>"><documentId>VALUE REDACTED></documentId><applicationId>VALUE REDACTED></applicationId></QueueDocument></soap:Body></soap:Envelope> 20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 55, column 9: System.HttpResponse[Status=OK, StatusCode=200] 20100225212803.213:Class.LeadIVAULTCallout.LeadIVAULTCalloutPOST: line 58, column 9: <?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><QueueDocumentResponse xmlns="<URL VALUE REDACTED>"><QueueDocumentResult><success>true</success><returnValue>The operation completed normally</returnValue></QueueDocumentResult></QueueDocumentResponse></soap:Body></soap:Envelope>

 

 

 

 

 So, in essence, I posting the SOAP call as a string.  The advantage is that this allows me to debug within the future call (something the WSDL2Apex seems to have issues with, from what I saw on other posts).  The disadvantage is that I'm using a cobbled system instead of the nice shiny one that SF offers.  So, that being said, If anybody wants to weigh in my earlier attempt, please feel free.  If, like me, you find you're having troubles, you might try this approach.

Also, if anybody looks at my workaround and has a way to make it more elegant, etc., please share.

 

This was selected as the best answer
Manoj_Manoj_

Hi I am facing the same issue. Did you happen to find a fix for this? Can you please help me out if you managed to find a fix?

 

Thanks,

Manoj

thecrmninjathecrmninja

Yes, I list it right above your comment.

 

The most important part is this....

 

 

        string SoapXMLBody;
                
        SoapXMLBody ='<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header>    <AuthSoapHeader 
xmlns="<URL VALUE REDACTED>"><UserName>'+UserName+'</UserName> 
<Password>'+Password+'</Password></AuthSoapHeader></soap:Header><soap:Body><QueueDocument 
xmlns="<URL VALUE REDACTED>"><documentId>'+DocumentID+'</documentId><applicationId>'+applicationId+'</applicationId></Q
ueueDocument></soap:Body></soap:Envelope>';

 

Basically, you use a string variable to store the soap structure and pass that to the web service via an HTTP POST call, constructing the call in a RESTful method.

 

Manoj_Manoj_

Thanks so much for the immediate response. Do you know if there is anyway if I can use soap (wsdl2apex) to achieve this?

 

I have a visualforce page that calls a apexclass that logins to a server and use the session id for further requests. The whole process needs to happen synchronously.

 

Thanks,

Manoj

thecrmninjathecrmninja

I wish I did know, because that's what I would be using myself.  There is just not a lot of documentation on overcoming what seem to be common WSDL2Apex obstacles.  That is how I stumbled on this solution (which, in fairness, somebody else came up with).  When I attempted to use W2A, I was basically dead in the water.  The minute I took this approach, I was working perfectly.

 

I think that you are still OK to call Synchronously (even though my example is async).  I haven't done this myself but I figure that you can do what I do in my trigger (create a list of IDs, or just a single ID) and pass that into the HTTP Request method.  Have you tried this?  Just building the webservice call as a RESTful within the class tied to your visualforce page?  Also, keep in mind that you will want to adapt the timeout limits for your action, since it sounds like you will be wanting to conduct a number of functions in a single session. 

 

 

Manoj_Manoj_

Thanks so much for pointing me out to a different direction. I am in a deadlock with W2A and I think your suggestion make a good sense. I am gonna start developing this on how you suggested and see if this works.

 

Additionally I will try logging this case with salesforce support and if (at all) I get a solution to this using the W2A I will post that as well.

 

Thanks,

Manoj

 

vanessenvanessen

i think that you are the person who will be able to help me. my problem is as follows:

 

I have to integrate salesforce with magento which uses a wsdl with format RPC/encoded.

I have the architecture of the wsdl, and i also have the url to the wsdl.

 

As salesforce do not understand RPC/encoded , i was skipping the part of wsdl2Apex and i am trying the HTTP request/response. but i do not know where to start.I need to call a method from the wsdl with 3 parameters a username,a pwd and an id ,and expect to get a list of info.

 

 So my questions are:

 

1. which url to use for the endpoint? the same as specified in the wsdl soap:address e.g http://190.160.1.31/soap/xx_reservation.php or to the wsdl itself : http://petest.polarBox.com/soap/xx_reservation.wsdl

 

2. How do i call the method from HTTP Callout??? in the .setBody() -- how do i construct it?

 

3. How do i pass a parameter to the function call??

 

thanks in anticipation for your help.

thecrmninjathecrmninja

1. Your endpoint should be NOT be the address for the WSDL itself but the other address is not what I'm accustomed to seeing for endpoints I've dealt with.  It's probably what you should use but I just do not recall seeing PHP on the end for endpoints i've built in the past.  But, you can try it and see if it works.  :D.

 

req.setBody(SoapXML);

 

3. Again, look at the string i build in that post from 05-21-2010 04:53 AM.....  inbewteen the plus signs, you will see where I'm setting parameters as part of the SOAP Header.  What I do, is establish Variables at the beginning of the class (mine are string variables) that store values such as Username, Password, DocumentID, ApplicationID, etc. Then in those get passed in paramater markups like so...

 

<UserName>'+UserName+'</UserName> 

 with each parameter coming one after another.  The order of this should be clear in your WSDL file as it will show each item.  Most WSDL files have a sample of a SOAP header, which would be your launching off point for this.  It's what I cover when setting the "SoapXMLBody" variable in the example I provided above.

 

 

 

 

vanessenvanessen

thanks for your reply....i will try it.and revert back to you ,if there is any question.

thanks again

vanessenvanessen

in my wsdl, the part where the function is defined is this :

 

the message part:

 

 

<wsdl:message name="getVoucherInfoRequest">

 <wsdl:part name="voucher_no" type="xs:string"/>

 <wsdl:part name="identity_acces" type="xs:string"/>

 <wsdl:part name="pass_acces" type="xs:string"/>

</wsdl:message>

 

 

the operation part:

 

 

<wsdl:operation name="getVoucherInfo" parameterOrder="voucher_no identity_acces pass_acces">
 <wsdl:input message="impl:getVoucherInfoRequest" name="getVoucherInfoRequest"/>
 <wsdl:output message="impl:getVoucherInfoResponse" name="getVoucherInfoResponse"/>
</wsdl:operation>
As you can see,my function takes 3 parameters.
1.  Should i pass the identity_access and pass_access in the header or in the body?
2. what is the tag to be used to specify the method to be call : <operation>getVoucherInfo</operation> ?
3. In your sample code,what is the <URL VALUE REDACTED> for the <AuthSoapHeader 
xmlns="<URL VALUE REDACTED>" .....
thanks for your reply.

 

thecrmninjathecrmninja

1. I pass them in the body, so I would try that if I was you.

2. You will see how I approached this in my example, my action was "QueueDocument" and start and end tags for this sit around the soap body.

3. I cannot give you the precise URL values but they were the web address for the Webservice that I was calling.  So, whatever the public URL is for this webservice you are calling to, is what you should have in those areas (without the brackets. ie:  xmlns="http://webserviceSERVERSurl/subpage.server.com/", for example)

vanessenvanessen

i am using an RPC/encoded wsdl file.So will your code apply for this too?

because in the RPC/encoded wsdl i received , there were no tags that resemble those tag you are using. Does this cause a problem.

 

because when i run, at one time i received time out and when i modify based on the url with the php extension i receive lots of errors.

thecrmninjathecrmninja

Then, you need to use the method that generates the errors and research each error, adjusting your approach until you overcome them all.  This is what I had to do with my SOAP PUT call (I had MANY errors to work through).  I'm not familiar enough with RPC Encoding to resolve the problems there on your behalf.  But, from what little research I have done(http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/), I don't think you will have any fundamental problems with it.  This SHOULD be because the approach here is all based off of constructing a simple string so SF will not be in your way (since it is doing very little work).  This will have the benefit of allowing you to focus on the Webservice side and overcoming your errors.  My suspicion is that your errors are a matter of how you are constructing your SOAP file.  Keep tweaking it to see if you can start eliminating errors.

vanessenvanessen

ok thank you....i will try it.