Create your own ZOO-Services

ZOO-Services are quite easy to create once you have installed the ZOO Kernel and have chosen code (in the language of your choice) to turn into a ZOO service. Here are some HelloWorlds in Python, PHP, Java, C# and JavaScript with links to their corresponding .zcfg files.

General information

The function of the process for each programming language take three arguments: the main configuration, inputs and outputs.

Note

The service must return 3 if the process run successfully

Note

The service must return 4 if the process ended with an error

Python

You’ll find here information needed to deploy your own Python Services Provider.

ZOO-API

From your python module where you define your services, you can access the ZOO-API by importing the zoo module. No need to install anything here, the module will be automatically created from the ZOO-Kernel code at runtime.

The following attributes are available from the ZOO-API :

SERVICE_SUCCEEDED

Value to return in case your service end successfully.

SERVICE_FAILED

Value to retrun in case of failure.

The following functions are defined in the ZOO-API:

_(strToTranslate)

return the translated string (using the “zoo-service” textdomain)

update_status(dictConf,iPourcent)

update the status of the running service

trace(strMessage)

write a message to the ZOO-Kernel log file

info(strMessage)

write an information message to the ZOO-Kernel log file

success(strMessage)

write a success message to the ZOO-Kernel log file

warning(strMessage)

write a warning message to the ZOO-Kernel log file

error(strMessage)

write an error message to the ZOO-Kernel log file

critical(strMessage)

write a critical message to the ZOO-Kernel log file

Python ZCFG requirements

Note

For each Service provided by your ZOO Python Services Provider, the ZCFG File must be named the same as the Python module function name (also the case of characters is important).

The ZCFG file should contain the following :

serviceType

Python

serviceProvider

The name of the Python module to use as a ZOO Service Provider. For instance, if your script, located in the same directory as your ZOO Kernel, was named my_module.py then you should use my_module (the Python module name) for the serviceProvider value in ZCFG file.

Python Data Structure used

The three parameters of the function are passed to the Python module as dictionaries.

Following you’ll find an example for each parameters

Main configuration

Main configuration contains several informations, some of them are really useful to develop your service. Following an example

{
'main': {'lang': 'en-UK',
         'language': 'en-US',
         'encoding': 'utf-8',
         'dataPath': '/var/www/tmp',
         'tmpPath': '/var/www/tmp',
         'version': '1.0.0',
         'mapserverAddress': 'http://localhost/cgi-bin/mapserv',
         'isSoap': 'false',
         'tmpUrl': 'http://localhost/tmp/',
         'serverAddress': 'http://localhost/zoo'
        },
'identification': {'keywords': 'WPS,GIS',
                   'abstract': 'WPS services for testing ZOO',
                   'fees': 'None',
                   'accessConstraints': 'none',
                   'title': 'testing services'
                  },
'lenv': {'status': '0',
         'soap': 'false',
         'cwd': '/usr/lib/cgi-bin',
         'sid': '24709'
        },
'env': {'DISPLAY': 'localhost:0'},
'provider': {'addressCountry': 'it',
             'positionName': 'Developer',
             'providerName': 'Name of provider',
             'addressAdministrativeArea': 'False',
             'phoneVoice': 'False',
             'addressCity': 'City',
             'providerSite': 'http://www.your.site',
             'addressPostalCode': '38122',
             'role': 'Developer',
             'addressDeliveryPoint': 'False',
             'phoneFacsimile': 'False',
             'addressElectronicMailAddress': 'your@email.com',
             'individualName': 'Your Name'
            }
}

Inputs

The inputs are somethings like this

{
'variable_name': {'minOccurs': '1',
                  'dataType': 'string',
                  'value': 'this_is_the_value',
                  'maxOccurs': '1',
                  'inRequest': 'true'
                 }
}

The access to the value you have to require for the value parameter, something like this

yourVariable = inputs['variable_name']['value']

Outputs

The outputs data as a structure really similar to the inputs one

{
'result': {'dataType': 'string',
           'inRequest': 'true',
          }
}

There is no 'value' parameter before you assign it

inputs['result']['value'] = yourOutputDataVariable

The return statement has to be an integer: corresponding to the service status code.

To add a message for the wrong result you can add the massage to conf["lenv"]["message"], for example:

conf["lenv"]["message"] = 'Your module return an error'

Sample ZOO Python Services Provider

The following code represents a simple ZOO Python Services Provider which provides only one Service, the HelloPy one.

import zoo
import sys
def HelloPy(conf,inputs,outputs):
   outputs["Result"]["value"]="Hello "+inputs["a"]["value"]+" from Python World !"
   return zoo.SERVICE_SUCCEEDED

PHP

ZOO-API

The ZOO-API for the PHP language is automatically available from your service code. The following functions are defined in the ZOO-API:

int zoo_SERVICE_SUCCEEDED()

return the value of SERVICE_SUCCEEDED

int zoo_SERVICE_FAILED()

return the value of SERVICE_FAILED

string zoo_Translate(string a)

return the translated string (using the “zoo-service” textdomain)

void zoo_UpdateStatus(Array conf,string message,int pourcent)

update the status of the running service

PHP ZCFG requirements

The ZCFG file should contain the following :

serviceType

PHP

serviceProvider

The name of the php script (ie. service.php) to use as a ZOO Service Provider.

PHP Data Structure used

The three parameters are passed to the PHP function as Arrays.

Sample ZOO PHP Services Provider

<?
function HelloPHP(&$main_conf,&$inputs,&$outputs){
   $tmp="Hello ".$inputs[S][value]." from PHP world !";
   $outputs["Result"]["value"]=zoo_Translate($tmp);
   return zoo_SERVICE_SUCCEEDED();
}
?>

Java

Specifically for the Java support, you may add the following three sections to your main.cfg file:

[java]:

This section is used to pass -D* parameters to the JVM created by the ZOO-Kernel to handle your ZOO-Service (see ref. 1 or ref. 2 for sample available). For each map a = b available in the [java] section, the option -Da=b will be passed to the JVM.

[javax]:

The section is used to pass -X* options to the JVM (see ref.). For each map a = b available in the [javax] section, the option -Xab will be passed to the JVM (ie. set mx=2G to pass -Xmx2G).

[javaxx]:

This section is used to pass -XX:* parameters to the JVM created by the ZOO-Kernel to handle your ZOO-Service (see ref. 1 or ref. 2 for sample available). For each map a = b available in the [javaxx] section, the option -XX:a=b will be passed to the JVM. In case of a map a = minus (respectively a=plus) then the option -XX:-a (respectivelly -XX:+a) will be passed.

ZOO-API

Before you build your first ZOO-Service implemented in Java, it is recommended that you first build the ZOO class of the Java ZOO-API.

Note

You should build ZOO-Kernel prior to follow this instructions.

To build the ZOO.class of the ZOO-API for Java, use the following command:

cd zoo-api/java
make

Note

running the previous commands will require that both javac and javah are in your PATH.

You should copy the libZOO.so in a place Java can find it. In case you have defined the java.library.path key as /usr/lib/cgi-bin (in the [java] section), then you should copy it there.

cp libZOO.so /usr/lib/cgi-bin

The ZOO-API provides the following functions:

String translate(String s):

This function call the internal ZOO-Kernel function responsible for searching a translation of s in the zoo-services dictionary.

void updateStatus(Hashmap conf,String pourcent,String message):

This function call the updateStatus ZOO-Kernel function responsible for updating the status of the running service (only usefull when the service has been called asynchronously).

Java ZCFG requirements

Note

For each Service provided by your ZOO Java Services Provider (your corresponding Java class), the ZCFG File should have the name of the Java public method corresponding to the service (case-sensitive).

The ZCFG file should contain the following :

serviceType

Java

serviceProvider

The name of the Java class to use as a ZOO Service Provider. For instance, if your java class, located in the same directory as your ZOO-Kernel, was named HelloJava.class then you should use HelloJava.

Java Data Structure used

The three parameters are passed to the Java function as java.util.HashMap.

Sample ZOO Java Services Provider

import java.util.*;
public class HelloJava {
  public static int HelloWorldJava(HashMap conf,HashMap inputs, HashMap outputs) {
     HashMap hm1 = new HashMap();
     hm1.put("dataType","string");
     HashMap tmp=(HashMap)(inputs.get("S"));
     java.lang.String v=tmp.get("value").toString();
     hm1.put("value","Hello "+v+" from JAVA WOrld !");
     outputs.put("Result",hm1);
     System.err.println("Hello from JAVA WOrld !");
     return ZOO.SERVICE_SUCCEEDED;
  }
}

C#

Specifically for the C# support, you should add the following section to your main.cfg file.

[mono]:

This section is used to define both libPath and etcPath required by the Mono .NET Framework.

ZOO-API

Before you build your first ZOO-Service implemented in Mono, you should first build the ZMaps.dll containing the Mono ZOO-API.

Note

You should build ZOO-Kernel prior to follow this instructions.

cd zoo-api/mono
make

Then you should copy the ZMaps.dll in your servicePath or in the directory where your zoo_loader.cgi file is stored.

The ZOO-API is available from a C# class named ZOO_API and provides the following static variables:

int SERVICE_SUCCEEDED:

Value to return in case your service end successfully.

int SERVICE_FAILED:

Value to retrun in case of failure.

The ZOO-API provides the following static functions:

string Translate(String s):

This function call the internal ZOO-Kernel function responsible for searching a translation of s in the zoo-services dictionary.

void UpdateStatus(ZMaps conf,String pourcent,String message):

This function call the updateStatus ZOO-Kernel function responsible for updating the status of the running service (only usefull when the service has been called asynchronously).

C# ZCFG requirements

Note

For each Service provided by your ZOO Mono Services Provider (your corresponding Mono class), the ZCFG File should have the name of the Mono public static function corresponding to the service (case-sensitive).

The ZCFG file should contain the following :

serviceType

Mono

serviceProvider

The full name of the C# dll containing the ZOO-Service Provider (including .dll).

serviceNameSpace

The namespace of the C# class containing the ZOO-Service Provider.

serviceClass

The name of the C# class containing the ZOO-Service Provider definition.

C# Data Structure used

The three parameters of the function are passed to the Mono static function as ZMaps which are basically Dictionary<String,_ZMaps>.

Sample ZOO C# Services Provider

Javascript (SpiderMonkey)

ZOO API

If you need to use ZOO API in your service, you have first to copy zoo-api.js and zoo-proj4js.js where your services are located (for example in Unix system probably in /usr/lib/cgi-bin/

Javascript ZCFG requirements

Note

For each Service provided by your ZOO Javascript Services Provider, the ZCFG File must be named the same as the Javascript function name (also the case of characters is important).

The ZCFG file should contain the following :

serviceType

JS

serviceProvider

The name of the JavaScript file to use as a ZOO Service Provider. For instance, if your script, located in the same directory as your ZOO Kernel, was named my_module.js then you should use my_module.js.

Javascript Data Structure used

The three parameters of the function are passed to the JavaScript function as Object.

Sample ZOO Javascript Services Provider

function hellojs(conf,inputs,outputs){
   outputs=new Array();
   outputs={};
   outputs["result"]["value"]="Hello "+inputs["S"]["value"]+" from JS World !";
   return Array(3,outputs);
}

Javascript (Node.js)

Environment

The Node.js services environment offers a fully functional Node.js environment. The gdal-async, proj4 and wps-js-52-north modules are supported out of the box and can be imported/required. Loading of external CJS and ES6 modules installed from the NPM registry in a node_modules sub-directory is also supported when this directory is present in the same directory as the service JavaScript file.

Javascript ZCFG requirements

Note

For each Service provided by your ZOO Javascript Services Provider, the ZCFG File must be named the same as the exported Javascript function name (also the case of characters is important).

The ZCFG file should contain the following :

serviceType

NodeJS

serviceProvider

The name of the JavaScript file to use as a ZOO Service Provider. For instance, if your script, located in the same directory as your ZOO Kernel, was named my_module.js then you should use my_module.js.

jsModuleType (optional, default is CJS)

The module type used, CJS for CommonJS or ES6 for ECMAScript 6 modules. CommonJS modules should contain a modules.export = { serviceName: entryFunction } while ECMAScript 6 modules should contain export serviceName.

inspector (optional, default false)

Enables the built-in debugger. When enabled the service won’t run until a V8 Inspector Protocol has connected to port 9229.

Javascript Data Structure used

The three parameters of the function are passed to the JavaScript function as Object. The main entry point function should return one of the predefined values: SERVICE_ACCEPTED, SERVICE_STARTED, SERVICE_PAUSED, SERVICE_SUCCEEDED or SERVICE_FAILED.

Sample ZOO Node.js Javascript Services Provider

function hellojs(conf,inputs,outputs){
   outputs["result"]["value"]="Hello "+inputs["S"]["value"]+" from JS World !";
   return SERVICE_SUCCEEDED;
}

module.exports = hellojs;

Using the Integrated Remote Debugger

The Node.js runtime supports debugging of Javascript services directly in their normal execution environment. The debugger is enabled by setting inspector to true in the service configuration file. Once enabled, the debugger will automatically pause the service upon launching it and it will wait for a V8 Inspector Protocol compliant client to connect to port 9229. The Chrome browser includes one such client that is accessible by typing chrome://inspect in the URL bar. Another popular debugging client is Visual Studio Code.

R

ZOO API

For using the R language from the ZOO-Project, you have first to copy minimal.r in the same directory as the ZOO-Kernel.

The ZOO-API is available from a R script and provide access to a global zoo environment which contains both static variables and also the dictionaries for outputs and conf:

int zoo[[“SERVICE_SUCCEEDED”]]:

Value to return in case your service end successfully.

int zoo[[“SERVICE_FAILED”]]:

Value to retrun in case of failure.

The ZOO-API provides the following functions:

string ZOOTranslate(String s):

This function call the internal ZOO-Kernel function responsible for searching a translation of s in the zoo-services dictionary.

void ZOOUpdateStatus(ZMaps conf,String pourcent):

This function call the updateStatus ZOO-Kernel function responsible for updating the status of the running service (only usefull when the service has been called asynchronously).

R ZCFG requirements

Note

For each Service provided by your ZOO R Services Provider, the ZCFG File must be named the same as the R function name (it is case-sensitive).

The ZCFG file should contain the following :

serviceType

R

serviceProvider

The name of the R file to use as a ZOO Service Provider. For instance, if your script, located in the same directory as your ZOO Kernel, was named my_module.r then you should use my_module.r.

R Data Structure used

The three parameters of the function are passed to the R function as R dictionaries.

The specificity of the R language make that it was easier to use global variales than passing parameters by reference as we do in other progamming languages. It is the reason why you will have to access outpus by using the global variable as for the main configuration dictionary.

Sample ZOO R Services Provider

source("minimal.r")

hellor <- function(a,b,c) {
    # Set the result
    zoo[["outputs"]][["Result"]][["value"]] <<- ZOOTranslate(paste("Hello",b[["S"]][["value"]],"from the R World!",sep=" "))
    # Return SERVICE_SUCCEEDEED
    return(zoo[["SERVICE_SUCCEEDEED"]])
}