Monday, July 18, 2011

Cascading WMS with deegree

In this post I want to explain how cascading a WMS works in deegree. Cascading a WMS can be useful to 'repair' broken WMS, restructure layer hierarchies or to hide multiple WMS behind one endpoint.

So how does cascading work in deegree? First of all, there's an abstract concept of a remote OWS data source. Currently there is only a WMS implementation, but more will follow. That means a remote WMS can be a resource in the workspace. That resource can then be used in your WMS configuration as a data source for a layer.

One important consequence is that one remote WMS data source means one data source. Although a WMS might typically have multiple layers and the config allows you to select multiple layers for cascading, it's still one resource. Let's have a look at an example:

<RemoteWMSStore xmlns="http://www.deegree.org/datasource/remoteows/wms"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.deegree.org/datasource/remoteows/wms remotewms.xsd"
configVersion="3.1.0">
  <CapabilitiesDocumentLocation
location="http://deegree3-testing.deegree.org/deegree-utah-demo/services?request=capabilities&amp;service=WMS&amp;version=1.1.1"/>
  <RequestedLayer>
    <Name>ZipCodes</Name>
  </RequestedLayer>
</RemoteWMSStore>

It's always required to specify a capabilities document. This can also be a local file instead of a request. Then you can specify one or more requested layers. That's it, everything else (available crs, formats etc.) will be determined from the capabilities.

Now to actually make it available as WMS layer in deegree just add a layer with the datasource ID:

<wms:RequestableLayer>
  <wms:Name>zipcodes</wms:Name>
  <wms:Title>Utah ZipCodes</wms:Title>
  <wms:RemoteWMSStoreId>zipcodes</wms:RemoteWMSStoreId>
</wms:RequestableLayer>
 
And that's that, you're done.

But imagine the remote WMS has a slow png implementation, and you want to always request the map as jpeg. Also, transformation is broken and you want to let deegree always reproject the raster image. That's easy:

<RemoteWMSStore
xmlns="http://www.deegree.org/datasource/remoteows/wms"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.deegree.org/datasource/remoteows/wms remotewms.xsd"
configVersion="3.1.0">
  <CapabilitiesDocumentLocation
    location="http://deegree3-testing.deegree.org/deegree-utah-demo/services?request=capabilities&amp;service=WMS&amp;version=1.1.1" />
  <DefaultRequestOptions>
    <ImageFormat transparent="false">image/jpeg</ImageFormat>
<DefaultCRS useAlways="true">EPSG:4326</DefaultCRS>
  </DefaultRequestOptions>
  <RequestedLayer>
    <Name>ZipCodes</Name>
  </RequestedLayer>
</RemoteWMSStore>

Please note that deegree will automatically reproject anyway, if the requested crs is not available in the remote WMS. Setting useAlways to true as in the example will force reprojection even for crs that the remote WMS claims to know.

The configuration you've seen so far is a kind of configuration where you tell deegree what you want to achieve on a high level. That's pretty nice, but sometimes one wants control on a lower level. Imagine you want to send a vendor specific parameter for all requests.

Let's say you really like red backgrounds:

<DefaultRequestOptions>
    <ImageFormat transparent="false">image/jpeg</ImageFormat>
    <Parameter use="allowOverride" scope="GetMap" name="bgcolor">0xff0000</Parameter>
</DefaultRequestOptions>
 
In this case, you'll have a red background as default, and the user can override it using BGCOLOR in a GetMap request. If the use-attribute is set to fixed, the parameter's value will always be used. The scope-attribute can be set to GetMap, GetFeatureInfo and All.

The DefaultRequestOptions block can also occur within a RequestedLayer section (named RequestOptions). In that case, the store will not request the layers in a single request, but will do multiple requests and combine them into a single map. That enables you to combine layers with different options, such as when two layers should be requested in different crs.

Last but not least, some WMS need authentication. Currently, only HTTP Basic is supported:

<HTTPBasicAuthentication>
<Username>myuser</Username>
<Password>s3cret</Password>
</HTTPBasicAuthentication> 
 
Another note on why cascading might be useful is WMS implementations that don't support proper GML output for featureinfo. deegree will read in the broken format and serve proper GML. There are currently workarounds for ArcIMS and MyWMS, but others should be easy to add. Just drop me a note. 

I hope that provides some insight on how to use deegree for cascading WMS. For a couple of examples you can check out the deegree-wms-remoteows-test module.

Edit: sorry for the crappy XML formatting, I'm still trying to figure out how to use blogger...