I have a ServiceCallout policy that looks like this:
<ServiceCallout name='SC-SendAnotherRequest'> <DisplayName>SC-SendAnotherRequest</DisplayName> <Request variable='extraRequest'> <Set> <Verb>GET</Verb> </Set> </Request> <Response>extraResponse</Response> <HTTPTargetConnection> <Properties> <Property name='success.codes'>2xx, 4xx, 5xx</Property> </Properties> <URL>{settings_targetUrl}</URL> </HTTPTargetConnection> </ServiceCallout>
The context variable settings_targetUrl is set to a URL.
When I try to import a proxy that contains such a policy, I get a validation error:
==> 400 { "code" : "messaging.config.beans.ProtocolMissingInURL", "message" : "Target Step SC-SendAnotherRequest: Protocol is missing in {settings_targetUrl}", "contexts" : [ ] }
I think there is a validation step that is looking for an explicit http or https in the URL element.
How can I set this dynamically?
Solved! Go to Solution.
I've run into this issue before. I believe you'll need to include the protocol, hostname, a slash, path, and query string (last two can go together). It seems as if the content of the XML URL element is being validated as a literal first. I thought I had a JIRA ticket for it.
So instead of this: <URL>{settings_targetUrl}</URL> Try: <URL>https://{settings_target_hostname}/{settings_target_path_and_querystr}</URL>
Diego's answer works. IF, however, you are not certain that the scheme will be http or https, then you need to use a different approach. The following works. Configure your ServiceCallout policy to set a dummy value in the URL and a Path in the request. Like this:
<ServiceCallout name='SC-SendAnotherRequest'> <DisplayName>SC-SendAnotherRequest</DisplayName> <Request variable='extraRequest'> <Set> <Verb>GET</Verb> <Path>{sc_urlPath}</Path> </Set> </Request> <Response>extraResponse</Response> <HTTPTargetConnection> <Properties> <Property name='success.codes'>2xx, 4xx, 5xx</Property> </Properties> <URL>http://dummy.this.will.get.set.dynamically</URL> </HTTPTargetConnection> </ServiceCallout>
In the flow prior to the ServiceCallout policy, you must set two variables:
servicecallout.SC-SendAnotherRequest.target.url sc_urlPath
The first one must follow the form servicecallout.POLICYNAME.target.url , where POLICYNAME is replaced by the name of your ServiceCallout policy. You can set this variable before the SC policy runs. However, the SC policy will use only the scheme and host from the URL that you set there, and will not use the path.
The second variable can be named anything you like. Just be consistent in the name you use when setting it, and the name you use when referencing it in the Path element. I chose sc_urlPath. This variable should contain just the path, including the leading slash, of the URL to request. It will be appended to the scheme://hostname which is set into the URL.
Supposing you have the complete URL you want to use for ServiceCallout, you need to dis-assemble that URL into two pieces: the first for the scheme+hostname, the second for the full url path. I accomplished this with a JS policy, like so:
// setTargetUrlVariables.js // ------------------------------------------------------------------ // // Set two variables to be use in ServiceCallout. // the base URI goes to: servicecallout.SC-SendAnotherRequest.target.url // the path goes to: sc_urlPath var urlvalue = context.getVariable('settings_serviceCalloutUrl'); var re = new RegExp('^(https?://[^/]+)(/.*)$'); var match = re.exec(urlvalue); if (match) { context.setVariable('servicecallout.SC-SendAnotherRequest.target.url', match[1]); context.setVariable('sc_urlPath', match[2]); }
You could parameterize that JS policy to make the variable names external. (use the Properties element in the JS policy).
It's a shame that it's this convoluted to set the URL dynamically for a ServiceCallout. But it IS possible.