Thursday, May 6, 2010

Apex No Operation Available Request Web Service Errors !

Sometimes while working with Salesforce Web Service APIs, we get “No Operation Available for Request” error. This error comes because the “Web service ENDPOINT URL” is not correct. In my case this error came when I was trying to use “apex.wsdl” for executing Apex test cases via my java code.

Here is the code sample that was failing for “No Operation Available For Request…/runTests”.

SoapBindingStub binding = (SoapBindingStub) new SforceServiceLocator()
		.getSoap();
LoginResult lr = binding.login(username, password);
binding._setProperty(SoapBindingStub.ENDPOINT_ADDRESS_PROPERTY, lr
		.getServerUrl());
SessionHeader sh = new SessionHeader();
sh.setSessionId(lr.getSessionId());
binding.setHeader(new SforceServiceLocator().getServiceName()
		.getNamespaceURI(), "SessionHeader", sh);
ApexBindingStub apexBinding = (ApexBindingStub) new ApexServiceLocator()
		.getApex();
/*
Line below was cause of problem, I was setting incorrect url for binding end point.
*/
apexBinding._setProperty(ApexBindingStub.ENDPOINT_ADDRESS_PROPERTY,
		lr.getServerUrl());

// Apex Session Header
com.sforce.soap._2006._08.apex.SessionHeader ash = new com.sforce.soap._2006._08.apex.SessionHeader();
ash.setSessionId(lr.getSessionId());
apexBinding.setHeader(new ApexServiceLocator().getServiceName()
		.getNamespaceURI(), "SessionHeader", ash);

RunTestsRequest runTestsRequest = new RunTestsRequest(false,
		new String[] { "TestFooBar" }, "myns", null);
RunTestsResult runTests = apexBinding.runTests(runTestsRequest);
System.out.println("Failures " + runTests.getNumFailures());

To make this working I need to point the Apex Binding Stub end point to the correct URL. Here is the fixed line

/*
Metadata WSDL/ENDPOINT URL : https://[api node].salesforce.com/services/Soap/m/18.0/[org-id]
Partner WSDL/ENDPOINT URL : https://[api node].salesforce.com/services/Soap/u/18.0/[org-id]

Both these URLs can be fetched via LoginResult.getServerUrl() and LoginResult.getMetadataServerUrl(). But there is no direct method  for Apex WSDL URL. 
Though Apex WSDL/ENDPOINT URL is simply one char change
https://[api node].salesforce.com/services/Soap/s/18.0/[org-id]
So here is the trick, and the above code snippet will work fine then.
*/
apexBinding._setProperty(ApexBindingStub.ENDPOINT_ADDRESS_PROPERTY,
	lr.getServerUrl().replaceAll("/u/", "/s/"));

Let me know any other such issues, specially with Enterprise WSDL, I haven’t tried it.

6 comments:

pragati said...

Hi,
I am calling the salesforce webservice through ConnectorConfig class. I am setting the Endpoint Url as:
config.setAuthEndpoint("https://cs4-api.salesforce.com/services/Soap/c/21.0");

I am calling the webservice present on sandbox thats why '/c/' in the Url is written. Still I am getting the exception "No operation available for request".

Any ideas?

Abhinav Gupta said...

Pragati,

You need to set Service End point also if you are using WSC > ConnectorConfig.

Call this API too :
void com.sforce.ws.ConnectorConfig.setServiceEndpoint(String serviceEndpoint)

Your URL is correct. Though best would be you try Tolerado framework for WSC, this framework relives you from all the hassle of session management and error handling. Its mentioned in salesforce blog and used by companies like Telegraph UK too.

Here is the Google Code Page for that : http://code.google.com/p/tolerado-sfdc-wsc-apis/

this guide will help you a lot : http://code.google.com/p/tolerado-sfdc-wsc-apis/wiki/GettingStartedGuide

Feel free to contact me, if you want any assistance in using it.

Abhinav

Abhinav Gupta said...

Pragati, If you still want to use WSC in raw form, check this post http://www.tgerm.com/2010/07/tolerado-sfdc-wsc-helper-apis.html it has detials

Anonymous said...

I'm trying to call a custom apex webservice using java. I was able to do this using Axis stubs. I want to achieve the same with out using Axis. I used wsdlc to generate stubs for custom web service and using SoapConnection class with a new ConnectorConfig object that has the sessionId and the loginUrl retrieved from the partner login. I get a No Operation Available error even after replacing the login url with "s" as indicated in your post.

Pragati said...

Thanks Abhinav for all your help.
tolerado blog helped me a lot.

Pragati

Abhinav Gupta said...

I am happy Pragati that Tolerado was helpful :)