.. _services-create: Create your own ZOO-Services ========================= :ref:`services_index` 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. .. contents:: :depth: 3 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 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: .. code-block:: python 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. .. code-block:: python 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 ****************************************** .. code-block:: php 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: .. code-block:: guess 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. .. code-block:: guess 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 ****************************************** .. code-block:: java 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. .. code-block:: guess 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``. Sample ZOO C# Services Provider ****************************************** .. literalinclude:: ../../zoo-project/zoo-services/hello-mono/test.cs :language: csharp :lines: 24-100 Javascript ---------- ZOO API ********* If you need to use :ref:`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 ****************************************** .. code-block:: javascript function hellojs(conf,inputs,outputs){ outputs=new Array(); outputs={}; outputs["result"]["value"]="Hello "+inputs["S"]["value"]+" from JS World !"; return Array(3,outputs); } 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 ****************************************** .. code-block:: javascript 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"]]) }