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