[686] | 1 | .. _first_service: |
---|
| 2 | |
---|
| 3 | ******************************* |
---|
| 4 | Creating your first ZOO Service |
---|
| 5 | ******************************* |
---|
| 6 | |
---|
| 7 | .. contents:: Table of Contents |
---|
| 8 | :depth: 5 |
---|
| 9 | :backlinks: top |
---|
| 10 | |
---|
| 11 | Introduction |
---|
| 12 | ============ |
---|
| 13 | |
---|
| 14 | In this part, you will create and publish from a simple ZOO Service named |
---|
| 15 | ``Hello`` which will simply return a hello message containing the input value |
---|
| 16 | provided. It will be usefull to present in deeper details general concept on how ZOO-Kernel works and handles request. |
---|
| 17 | |
---|
| 18 | Service and publication process overview |
---|
| 19 | ======================================== |
---|
| 20 | |
---|
| 21 | Before starting developing a ZOO Service, you should remember that in |
---|
| 22 | ZOO-Project, a Service is a couple made of: |
---|
| 23 | |
---|
| 24 | * a metadata file: a ZOO Service Configuration File (ZCFG) containing metadata |
---|
| 25 | informations about a Service (providing informations about default / supported |
---|
| 26 | inputs and outputs for a Service) |
---|
| 27 | * a Services Provider: it depends on the programming language used, but for Python it |
---|
| 28 | is a module and for JavaScript a script file. |
---|
| 29 | |
---|
| 30 | To publish your Service, which means make your ZOO Kernel aware of its presence, |
---|
| 31 | you should copy a ZCFG file in the directory where ``zoo_loader.cgi`` is located (in this workshop, ``/usr/lib/cgi-bin``). |
---|
| 32 | |
---|
| 33 | .. warning:: only the ZCFG file is required for the Service to be considerate as |
---|
| 34 | available. So if you don't get the Service Provider, obviously your Execute |
---|
| 35 | request will fail as we will discuss later. |
---|
| 36 | |
---|
| 37 | Before publication, you should store your ongoing work, so you'll start by |
---|
| 38 | creating a directory to store the files of your Services Provider: |
---|
| 39 | |
---|
| 40 | .. code-block:: none |
---|
| 41 | |
---|
| 42 | mkdir -p /home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/cgi-env |
---|
| 43 | |
---|
| 44 | Once both the ZCFG and the Python module are both ready, you can publish simply |
---|
| 45 | by copying the corresponding files in the same directory as the ZOO-Kernel. |
---|
| 46 | |
---|
| 47 | Creating your first ZCFG file |
---|
| 48 | ============================= |
---|
| 49 | |
---|
| 50 | You will start by creating the ZCFG file for the ``Hello`` Service. Edit the |
---|
| 51 | ``/home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/Hello.zcfg`` file |
---|
| 52 | and add the following content: |
---|
| 53 | |
---|
| 54 | .. code-block:: none |
---|
| 55 | :linenos: |
---|
| 56 | |
---|
| 57 | [Hello] |
---|
| 58 | Title = Return a hello message. |
---|
| 59 | Abstract = Create a welcome string. |
---|
| 60 | processVersion = 2 |
---|
| 61 | storeSupported = true |
---|
| 62 | statusSupported = true |
---|
| 63 | serviceProvider = test_service |
---|
| 64 | serviceType = Python |
---|
| 65 | <DataInputs> |
---|
| 66 | [name] |
---|
| 67 | Title = Input string |
---|
| 68 | Abstract = The string to insert in the hello message. |
---|
| 69 | minOccurs = 1 |
---|
| 70 | maxOccurs = 1 |
---|
| 71 | <LiteralData> |
---|
| 72 | dataType = string |
---|
| 73 | <Default /> |
---|
| 74 | </LiteralData> |
---|
| 75 | </DataInputs> |
---|
| 76 | <DataOutputs> |
---|
| 77 | [Result] |
---|
| 78 | Title = The resulting string |
---|
| 79 | Abstract = The hello message containing the input string |
---|
| 80 | <ComplexData> |
---|
| 81 | <LiteralData> |
---|
| 82 | dataType = string |
---|
| 83 | <Default /> |
---|
| 84 | </LiteralData> |
---|
| 85 | </ComplexData> |
---|
| 86 | </DataOutputs> |
---|
| 87 | |
---|
| 88 | .. note:: the name of the ZCFG file and the name between braket (here ``[Hello]``) |
---|
| 89 | should be the same and correspond to the function name you will define in your |
---|
| 90 | Services provider. |
---|
| 91 | |
---|
| 92 | As you can see in the ZOO Service Configuration File presented above it is divided into |
---|
| 93 | three distinct sections: |
---|
| 94 | #. Main Metadata information (from line 2 to 8) |
---|
| 95 | #. List of Inputs metadata information (from 9 line to 20) |
---|
| 96 | #. List of Outputs metadata information (from line 21 to 36) |
---|
| 97 | |
---|
| 98 | You can get more informations about ZCFG from `the reference documentation |
---|
| 99 | <http://zoo-project.org/docs/services/zcfg-reference.html>`__. |
---|
| 100 | |
---|
| 101 | If you copy the ``Hello.zcfg`` file in the same directory as your ZOO Kernel |
---|
| 102 | then you will be able to request for DescribeProcess using the ``Hello`` |
---|
| 103 | ``Identifier``. The ``Hello`` service should also be listed from Capabilities |
---|
| 104 | document. |
---|
| 105 | |
---|
| 106 | .. code-block:: none |
---|
| 107 | cp /home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/cgi-env/Hello.zcfg /usr/lib/cgi-bin |
---|
| 108 | |
---|
| 109 | Test requests |
---|
| 110 | ================= |
---|
| 111 | |
---|
| 112 | In this section you will tests each WPS requests : GetCapabilities, |
---|
| 113 | DescribeProcess and Execute. Note that only GetCapabilities and DescribeProcess |
---|
| 114 | should work at this step. |
---|
| 115 | |
---|
| 116 | Test the GetCapabilities request |
---|
| 117 | -------------------------------- |
---|
| 118 | |
---|
| 119 | If you run the ``GetCapabilities`` request: |
---|
| 120 | |
---|
| 121 | .. code-block:: none |
---|
| 122 | |
---|
| 123 | http://localhost/cgi-bin/zoo_loader.cgi?request=GetCapabilities&service=WPS |
---|
| 124 | |
---|
| 125 | Now, you should find your Hello Service in a ``Process`` node in |
---|
| 126 | ``ProcessOfferings``: |
---|
| 127 | |
---|
| 128 | .. code-block:: xml |
---|
| 129 | |
---|
| 130 | <wps:Process wps:processVersion="2"> |
---|
| 131 | <ows:Identifier>Hello</ows:Identifier> |
---|
| 132 | <ows:Title>Return a hello message.</ows:Title> |
---|
| 133 | <ows:Abstract>Create a welcome string.</ows:Abstract> |
---|
| 134 | </wps:Process> |
---|
| 135 | |
---|
| 136 | Test the DescribeProcess request |
---|
| 137 | -------------------------------- |
---|
| 138 | |
---|
| 139 | You can access the ``ProcessDescription`` of the ``Hello`` service using the |
---|
| 140 | following ``DescribeProcess`` request: |
---|
| 141 | |
---|
| 142 | .. code-block:: none |
---|
| 143 | |
---|
| 144 | http://localhost/cgi-bin/zoo_loader.cgi?request=DescribeProcess&service=WPS&version=1.0.0&Identifier=Hello |
---|
| 145 | |
---|
| 146 | You should get the following response: |
---|
| 147 | |
---|
| 148 | .. code-block:: xml |
---|
| 149 | |
---|
| 150 | <wps:ProcessDescriptions xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsDescribeProcess_response.xsd" service="WPS" version="1.0.0" xml:lang="en-US"> |
---|
| 151 | <ProcessDescription wps:processVersion="2" storeSupported="true" statusSupported="true"> |
---|
| 152 | <ows:Identifier>Hello</ows:Identifier> |
---|
| 153 | <ows:Title>Return a hello message.</ows:Title> |
---|
| 154 | <ows:Abstract>Create a welcome string.</ows:Abstract> |
---|
| 155 | <DataInputs> |
---|
| 156 | <Input minOccurs="1" maxOccurs="1"> |
---|
| 157 | <ows:Identifier>name</ows:Identifier> |
---|
| 158 | <ows:Title>Input string</ows:Title> |
---|
| 159 | <ows:Abstract>The string to insert in the hello message.</ows:Abstract> |
---|
| 160 | <LiteralData> |
---|
| 161 | <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType> |
---|
| 162 | <ows:AnyValue/> |
---|
| 163 | </LiteralData> |
---|
| 164 | </Input> |
---|
| 165 | </DataInputs> |
---|
| 166 | <ProcessOutputs> |
---|
| 167 | <Output> |
---|
| 168 | <ows:Identifier>Result</ows:Identifier> |
---|
| 169 | <ows:Title>The resulting string</ows:Title> |
---|
| 170 | <ows:Abstract>The hello message containing the input string</ows:Abstract> |
---|
| 171 | <LiteralOutput> |
---|
| 172 | <ows:DataType ows:reference="http://www.w3.org/TR/xmlschema-2/#string">string</ows:DataType> |
---|
| 173 | </LiteralOutput> |
---|
| 174 | </Output> |
---|
| 175 | </ProcessOutputs> |
---|
| 176 | </ProcessDescription> |
---|
| 177 | </wps:ProcessDescriptions> |
---|
| 178 | |
---|
| 179 | Test the Execute request |
---|
| 180 | ------------------------ |
---|
| 181 | |
---|
| 182 | Obviously, you cannot run your Service because the Python file was not published |
---|
| 183 | yet. If you try the following ``Execute`` request: |
---|
| 184 | |
---|
| 185 | .. code-block:: none |
---|
| 186 | |
---|
| 187 | http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto |
---|
| 188 | |
---|
| 189 | You should get an ExceptionReport similar to the one provided in the following, |
---|
| 190 | which is normal behavior: |
---|
| 191 | |
---|
| 192 | .. code-block:: xml |
---|
| 193 | |
---|
| 194 | <ows:ExceptionReport xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd" xml:lang="en-US" version="1.1.0"> |
---|
| 195 | <ows:Exception exceptionCode="NoApplicableCode"> |
---|
| 196 | <ows:ExceptionText>Python module test_service cannot be loaded.</ows:ExceptionText> |
---|
| 197 | </ows:Exception> |
---|
| 198 | </ows:ExceptionReport> |
---|
| 199 | |
---|
| 200 | Implementing the Python Service |
---|
| 201 | ================================ |
---|
| 202 | |
---|
| 203 | General Principles |
---|
| 204 | ------------------ |
---|
| 205 | |
---|
| 206 | The most important thing you must know when implementing a new ZOO-Services |
---|
| 207 | using the Python language is that the function corresponding to your Service |
---|
| 208 | returns an integer value representing the status of execution |
---|
| 209 | (``SERVICE_FAILED`` [#f1]_ or ``SERVICE_SUCCEEDED`` [#f2]_) and takes three |
---|
| 210 | arguments (`Python dictionaries |
---|
| 211 | <http://docs.python.org/tutorial/datastructures.html#dictionaries>`__): |
---|
| 212 | |
---|
| 213 | - ``conf`` : the main environment configuration (corresponding to the main.cfg content) |
---|
| 214 | - ``inputs`` : the requested / default inputs (used to access input values) |
---|
| 215 | - ``outputs`` : the requested / default outputs (used to store computation result) |
---|
| 216 | |
---|
| 217 | .. note:: when your service return ``SERVICE_FAILED`` you can set |
---|
| 218 | ``conf["lenv"]["message"]`` to add a personalized message in the ExceptionReport |
---|
| 219 | returned by the ZOO Kernel in such case. |
---|
| 220 | |
---|
| 221 | You get in the following a sample ``conf`` value based on the ``main.cfg`` file you |
---|
| 222 | saw `before <using_zoo_from_osgeolivevm.html#zoo-kernel-configuration>`__. |
---|
| 223 | |
---|
| 224 | .. code-block:: javascript |
---|
| 225 | :linenos: |
---|
| 226 | |
---|
| 227 | { |
---|
| 228 | "main": { |
---|
| 229 | language: "en-US", |
---|
| 230 | lang: "fr-FR,ja-JP", |
---|
| 231 | version: "1.0.0", |
---|
| 232 | encoding: "utf-8", |
---|
| 233 | serverAddress: "http://localhost/cgi-bin/zoo_loader.cgi", |
---|
| 234 | dataPath: "/var/www/zoows-demo/map/data", |
---|
| 235 | tmpPath: "/var/www/temp", |
---|
| 236 | tmpUrl: "../temp", |
---|
| 237 | cacheDir: "/var/www/temp/" |
---|
| 238 | }, |
---|
| 239 | "identification": { |
---|
| 240 | title: "The ZOO-Project OSGeoLiveDVD Server 2012", |
---|
| 241 | keywords: "WPS,GIS,buffer", |
---|
| 242 | abstract: "Demo version of Zoo-Project for OSGeoLiveDVD 2012. See http://www.zoo-project.org", |
---|
| 243 | accessConstraints: "none", |
---|
| 244 | fees: "None" |
---|
| 245 | }, |
---|
| 246 | "provider": { |
---|
| 247 | positionName: "Developer", |
---|
| 248 | providerName: "ZOO-Project", |
---|
| 249 | addressAdministrativeArea: "Lattes", |
---|
| 250 | addressCountry: "fr", |
---|
| 251 | phoneVoice: "False", |
---|
| 252 | addressPostalCode: "34970", |
---|
| 253 | role: "Dev", |
---|
| 254 | providerSite: "http://www.zoo-project.org", |
---|
| 255 | phoneFacsimile: "False", |
---|
| 256 | addressElectronicMailAddress: "gerald.fenoy@geolabs.fr", |
---|
| 257 | addressCity: "Denver", |
---|
| 258 | individualName: "Gérald FENOY" |
---|
| 259 | } |
---|
| 260 | |
---|
| 261 | In the following you get a sample outputs value passed to a Python or a JavaScript Service: |
---|
| 262 | |
---|
| 263 | .. code-block:: javascript |
---|
| 264 | :linenos: |
---|
| 265 | |
---|
| 266 | { |
---|
| 267 | 'Result': { |
---|
| 268 | 'mimeType': 'application/json', |
---|
| 269 | 'inRequest': 'true', |
---|
| 270 | 'encoding': 'UTF-8' |
---|
| 271 | } |
---|
| 272 | } |
---|
| 273 | |
---|
| 274 | .. note:: the ``inRequest`` value is set internally by the ZOO-Kernel and can be used to determine from the Service if the key was provided in the request. |
---|
| 275 | |
---|
| 276 | The Hello Service |
---|
| 277 | ------------------------ |
---|
| 278 | |
---|
| 279 | You can copy and paste the following into the |
---|
| 280 | ``/home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/cgi-env/test_service.py`` file. |
---|
| 281 | |
---|
| 282 | .. code-block:: python |
---|
| 283 | |
---|
| 284 | def Hello(conf,inputs,outputs): |
---|
| 285 | outputs["Result"]["value"]=\ |
---|
| 286 | "Hello "+inputs["name"]["value"]+" from the ZOO-Project Python world !" |
---|
| 287 | return 3 |
---|
| 288 | |
---|
| 289 | Once you finish editing the file, you should copy it in the ``/usr/lib/cgi-bin`` directory: |
---|
| 290 | |
---|
| 291 | .. code-block:: none |
---|
| 292 | |
---|
| 293 | sudo cp /home/user/zoo-ws-2012/src/zoo-project/zoo-services/ws_sp/cgi-env/* /usr/lib/cgi-bin |
---|
| 294 | |
---|
| 295 | |
---|
| 296 | Interracting with your service using Execute requests |
---|
| 297 | ===================================================== |
---|
| 298 | |
---|
| 299 | Now, you can request for Execute using the following basic url: |
---|
| 300 | |
---|
| 301 | .. code-block:: none |
---|
| 302 | |
---|
| 303 | http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto |
---|
| 304 | |
---|
| 305 | You can request the WPS Server to return a XML WPS Response containing the result of |
---|
| 306 | your computation, requesting for ResponseDocument or you can access the data directly |
---|
| 307 | requesting for RawDataOutput. |
---|
| 308 | |
---|
| 309 | * Sample request using the RawDataOutput parameter: |
---|
| 310 | |
---|
| 311 | .. code-block:: none |
---|
| 312 | |
---|
| 313 | http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&RawDataOutput=Result |
---|
| 314 | |
---|
| 315 | * Sample request using the default ResponseDocument parameter: |
---|
| 316 | |
---|
| 317 | .. code-block:: none |
---|
| 318 | |
---|
| 319 | http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result |
---|
| 320 | |
---|
| 321 | When you are using ResponseDocument there is specific attribut you can use to ask |
---|
| 322 | the ZOO Kernel to store the result: ``asReference``. You can use the following example: |
---|
| 323 | |
---|
| 324 | .. code-block:: none |
---|
| 325 | |
---|
| 326 | http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result@asReference=true |
---|
| 327 | |
---|
| 328 | When computation take long time, the client should request setting both |
---|
| 329 | ``storeExecuteResponse`` and ``status`` parameter to true. This will make the ZOO |
---|
| 330 | Kernel directly return a response containing a ``statusLocation`` attribut which can be |
---|
| 331 | used to access the status of an ongoing service or the result when the process ended. |
---|
| 332 | |
---|
| 333 | .. code-block:: none |
---|
| 334 | |
---|
| 335 | http://localhost/cgi-bin/zoo_loader.cgi?request=Execute&service=WPS&version=1.0.0&Identifier=Hello&DataInputs=name=toto&ResponseDocument=Result&storeExecuteResponse=true&status=true |
---|
| 336 | |
---|
| 337 | Conclusion |
---|
| 338 | ========== |
---|
| 339 | |
---|
| 340 | Even if this first service was really simple it was useful to illustrate how the |
---|
| 341 | ZOO-Kernel fill ``conf``, ``inputs`` and ``outputs`` parameter prior to load |
---|
| 342 | and run your function service, how to write a ZCFG file, how to publish a Services |
---|
| 343 | Provider by placing the ZCFG and Python files in the same directory as the |
---|
| 344 | ZOO-Kernel, then how to interract with your service using both |
---|
| 345 | ``GetCapabilities``, ``DescribeProcess`` and ``Execute`` requesr. We will see |
---|
| 346 | in the `next section <ogr_base_vect_ops.html>`__ how to write similar requests |
---|
| 347 | using the XML syntax. |
---|
| 348 | |
---|
| 349 | .. rubric:: Footnotes |
---|
| 350 | |
---|
| 351 | .. [#f1] ``SERVICE_FAILED=4`` |
---|
| 352 | .. [#f2] ``SERVICE_SUCCEEDED=3`` |
---|
| 353 | |
---|