When the product server requests a product from a backend service it makes that request by sending an XML message wrapped in a SOAP envelop. The sub-elements below the <backend_request> element can appear in any order. The XML below is an example of such a message. It's rather long, but not too complicated. Let's break it down section by section. The only folks that should be interested in this information are those folks that are writing a new service and therefore need to know how the service will get the information it needs to create the requested product. We don't recommend sending requests directly to backend services, send your requests to the product server and let it handle all the details of contacting the services.
<?xml version="1.0" encoding="UTF-8"?>
<backend_request>
<region ID="region_0">
<x_lo>-180.0</x_lo>
<x_hi>180.0</x_hi>
<y_lo>-89.0</y_lo>
<y_hi>89.0</y_hi>
<t_lo>15-Jan</t_lo>
<t_hi>15-Jan</t_hi>
</region>
<properties>
<property_group type="las">
<property>
<name>debug</name>
<value>debug</value>
</property>
</property_group>
<property_group type="operation">
<property>
<name>service</name>
<value>ferret</value>
</property>
<property>
<name>service_action</name>
<value>Plot_2D_XY</value>
</property>
<property>
<name>name</name>
<value>2D Plot in XY</value>
</property>
<property>
<name>ID</name>
<value>Plot_2D_XY</value>
</property>
<property>
<name>key</name>
<value>811BD26ADE822087556BABF97DBE950F</value>
</property>
</property_group>
<property_group type="ferret">
<property>
<name>view</name>
<value>xy</value>
</property>
<property>
<name>fill_type</name>
<value>fill</value>
</property>
<property>
<name>size</name>
<value>0.5</value>
</property>
<property>
<name>interpolate_data</name>
<value>false</value>
</property>
<property>
<name>service_action</name>
<value>Plot_2D_XY</value>
</property>
<property>
<name>land_type</name>
<value>contour</value>
</property>
<property>
<name>format</name>
<value>shade</value>
</property>
</property_group>
</properties>
<dataObjects>
<data url="coads_climatology" var="airt" title="AIR TEMPERATURE" xpath="/lasdata/datasets/coads_climatology_cdf/variables/airt" dataset_url="file:coads_climatology" dataset_name="COADS climatology" dataset_ID="coads_climatology_cdf" name="AIR TEMPERATURE" units="DEG C" ID="airt" points="xyt" intervals="xyt" grid_type="regular">
<region IDREF="region_0" />
<properties>
<property_group type="my_property_group">
<property>
<name>one_property</name>
<value>This first one.</value>
</property>
<property>
<name>another_property</name>
<value>A different one.</value>
</property>
</property_group>
<property_group type="product_server">
<property>
<name>ui_timeout</name>
<value>1000</value>
</property>
<property>
<name>ps_timeout</name>
<value>3600</value>
</property>
<property>
<name>use_cache</name>
<value>false</value>
</property>
</property_group>
</properties>
</data>
</dataObjects>
<response ID="PlotResp">
<result type="image" ID="plot_image" streamable="true" mime_type="image/png" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_plot_image.gif" index="0" />
<result type="ps" ID="plot_postscript" streamable="true" mime_type="application/postscript" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_plot_postscript.ps" index="1" />
<result type="image" ID="ref_map" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_ref_map.gif" index="2" />
<result type="map_scale" ID="map_scale" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_map_scale.xml" index="3" />
<result type="debug" ID="debug" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_debug.txt" index="4" />
<result type="cancel" ID="cancel" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_cancel.txt" index="5" />
</response>
<remote />
</backend_request>
A <region> element is used to communicate to the service the xyzt region that is of interest for this operation. The region is assoicated with a data object (file, OPeNDAP URL, database request, etc.) via the a <region> element with an IDREF attribute. For example, a data object would be associated with this region using an element like this: <region IDREF="region_0"/>. We could have constructed the XML with the regions nested inside the data elements, but since they often repeat and had to be flattened out to be translated into something Ferret can understand, we chose to use the IDREFs. If a particular coordinate dimension does not exist in a particular data set, then the "hi" and "lo" elements for that axis can be left out.
<region ID="region_0">
<x_lo>-180.0</x_lo>
<x_hi>180.0</x_hi>
<y_lo>-89.0</y_lo>
<y_hi>89.0</y_hi>
<t_lo>15-Jan</t_lo>
<t_hi>15-Jan</t_hi>
</region>
In this example there are two sections of property elements. The first collection appears directly below the <backend_request> element. These are properties that were delivered to the product server via the UI Request that it was asked to operate upon. The second set of properties is nested below a particular data object. When the request has reached this stage, all of the properties have been "merged" and there should be no duplicat properties between these two sets. If a property appeared both in the data set configuration and the request, the appropriate value was selected from the two and that value and only that value appears in the merged set.
<properties>
<property_group type="las">
<property>
<name>debug</name>
<value>debug</value>
</property>
</property_group>
<property_group type="operation">
<property>
<name>service</name>
<value>ferret</value>
</property>
<property>
<name>service_action</name>
<value>Plot_2D_XY</value>
</property>
<property>
<name>name</name>
<value>2D Plot in XY</value>
</property>
<property>
<name>ID</name>
<value>Plot_2D_XY</value>
</property>
<property>
<name>key</name>
<value>811BD26ADE822087556BABF97DBE950F</value>
</property>
</property_group>
...
</properties>
<dataObjects>
...
<properties>
<property_group type="my_property_group">
<property>
<name>one_property</name>
<value>This first one.</value>
</property>
<property>
<name>another_property</name>
<value>A different one.</value>
</property>
</property_group>
...
The next collection of information is the data objects. As we've already discussed, each individual data object can contain a collection of properties. Additionally, each will contain a reference to a region element. The remaining information is all contained in attributes on the <data> element. These attributes are:
Attribute | meaning |
---|---|
url | The data access URL for this data object (a local file name or OPeNDAP URL). |
var | The name of the data variable (netCDF variable name, database column, etc). |
title | The descriptive title of the data variable. |
xpath | The XML XPath to this variable configuration in the LAS configuration XML. |
dataset_url | The value of the url attribute on the parent <dataset> element.* |
dataset_ID | The value of the ID attribute on the parent <dataset> element.* |
name | The variable XML name. |
units | The units of the data variable. |
ID | The unique XML ID of the variable element. |
points | Those dimensions (xyz and/or t) for which this variable is defined at a point. |
intervals | Those dimenstions (xyz and/or t) for which this variable is defined on an interval. |
grid_type | The type of the underlying grid (scattered or regular). |
<dataObjects>
<data url="coads_climatology" var="airt" title="AIR TEMPERATURE"
xpath="/lasdata/datasets/coads_climatology_cdf/variables/airt"
dataset_url="file:coads_climatology" dataset_name="COADS climatology"
dataset_ID="coads_climatology_cdf" name="AIR TEMPERATURE" units="DEG C"
ID="airt" points="xyt" intervals="xyt" grid_type="regular">
<region IDREF="region_0" />
<properties>
...
</properties>
</data>
</dataObjects>
*For the time being, attributes that are associated with the parent <dataset> element are included in the data object with a "dataset_" prefix. This is not very "XML like", but it works well for communicating the information to Ferret.
The informaiton in the <response> element is the product server's idea of what the response should look like (what should be included and where the information should be written). However, the service can (and will by necessity in the case of a remote service) change the values of the url attributes. And the service might not produce all of the expected result (either because it can't for some reason or because the property values it received told it not to). The product server will always check for the existence of a result before adding it to the cache. When writing an output template you should also check for the existence of a result before using it in the template (if the result was not created getResult() or getResultAsFile() will return an empty string).
<response ID="PlotResp">
<result type="image" ID="plot_image" streamable="true" mime_type="image/png" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_plot_image.gif" index="0" />
<result type="ps" ID="plot_postscript" streamable="true" mime_type="application/postscript" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_plot_postscript.ps" index="1" />
<result type="image" ID="ref_map" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_ref_map.gif" index="2" />
<result type="map_scale" ID="map_scale" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_map_scale.xml" index="3" />
<result type="debug" ID="debug" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_debug.txt" index="4" />
<result type="cancel" ID="cancel" file="/usr/local/tomcat/webapps/armstrong/output/811BD26ADE822087556BABF97DBE950F_cancel.txt" index="5" />
</response>
Finally, if the service is running on a remote host (relative to where the product server is running) then the backend service request will contain the <remote/> element. This tells the remote service to supply a URL where the product server can find each result.
<remote />