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.