5.3. Command handler

Command handlers define the mapping of server requests to functions to execute. This chapter introduces the standard command handler.

5.3.1. The standard command handler

Introduction

The Wolframe standard command handler is called directmap and named so in the configuration because it only declares a redirection of the commands to functions based on the document type and the command identifier specified by the client in the request.

The declarations of the Wolframe Standard Command Handler (directmap) are specified in a program source file with the extension '.dmap' that is declared in the configuration.

Example configuration

The following annotated configuration example declares (1) a program example.tdl written in the transaction definition language (TDL) to contain the function declarations that can be called by the command handler. It (2) declares the database with name pgdb to be used as the database for transactions. It (3) loads a description example.dmap that will declare the mappings of commands to the filters used and functions called. It (4) specifies the filter with name libxml2 to be used for documents of format XML and (5) the filter with name cjson to be used for documents of format JSON, if not specified else in example.dmap.

; Simple Data Processing Configuration Example
Processor
{
    ; Programs to load:
    Program example.tdl            ; (1) a program with functions (in TDL)
    Database pgdb                  ; (2) references transaction database

    ; Command handlers to load:
    Cmdhandler
    {
        Directmap                  ; the standard command handler
        {
            Program example.dmap   ; (3) description of command mappings

            Filter XML=libxml2     ; (4) std filter for XML document format
            Filter JSON=cjson      ; (5) std filter for JSON document format
        }
    }
}


		

Example command description

The following source example could be one of the example.dmap in the configuration example introduced above. It defines two commands. The first one links a command "insert" with document type "Customer" as content to a transaction function "doInsertCustomer". The content is validated automatically against a form named "Customer" if not explicitly defined else. The command has no result except that it succeeds or fails. The second example command links a command "get" with a document type "Employee" to a function "doSelectEmployee". The input is not validated and the transaction output is validated and mapped through the form "Employee".


COMMAND insert Customer CALL doInsertCustomer;
COMMAND get Employee SKIP CALL doSelectEmployee RETURN Employee;


		

Command description language

A command map description file like our example shown consists of instructions started with COMMAND and terminated by semicolon ';'. The first argument after COMMAND is the name of the command followed by the name of the document type of the input document. The name of the command is optional. If not specified the first argument after COMMAND names the input document type.

Keywords

Conflicts with keywords and names are solved by using strings instead of identifiers. The standard command handler description language has the following keywords:

COMMAND
CALL
CONTEXT
RETURN
SKIP
FILTER
INPUT
OUTPUT
AUTHORIZE

Simple document map

The following example shows the simplest possible declaration. It states that documents with the document type "Document" are forwarded to a function with the same name "Document".


COMMAND Document;

				

Command with action prefix

The next example adds a action name to the declaration. The implicit name of the function called is insertDocument:


COMMAND insert Document;

				

Explicit function name declaration

For declaring the function called explicitly like for example a function doInsertDocument we need to declare it with CALL <functionname>:


COMMAND insert Document CALL doInsertDocument;

				

Returned document declaration

The document type returned is specified with RETURN <doctype>:


COMMAND process Document RETURN Document;

				

or with explicit naming of a function called


COMMAND process Document CALL doProcessDocument RETURN Document;

				

Returned document meta data

We can define additional document meta data or overload existing document meta or inherited document meta from input or a referenced form in the output. This is done with a comma separated list of attribute assignments in curly brackets after the document type name like:


COMMAND process Document 
    CALL doProcessDocument
        RETURN Document { root = 'doc', schema = 'bla.com/schema' };

			

Skipping the document validation

If you want to skip the input document validation, either because you are dealing with legacy software where a strict definition of a schema is not possible or because the function called has strict typing and validates the input on its own (.NET,C++), then you can add a declaration SKIP:


COMMAND process Document SKIP
	CALL doProcessDocument RETURN Document;

				

The same you can specify for the output with a SKIP following the RETURN of the output declaration:


COMMAND process Document
	CALL doProcessDocument RETURN SKIP Document;

				

For being able to skip validation of output of a processed XML we have additionally to specify the root element as document meta data. This defintion can be part of a form declaration (not used for validation) or it can be specified after the RETURN SKIP and the document type identifier in a standard command handler instruction. The following example shows such a definition with 'list' as root element defined. Such a command definition makes sense for strongly typed languages like .NET or native C++ where data validation can be delagated completely to the strongly typed structure definition of the called function.


COMMAND process Document
	CALL doProcessDocument RETURN SKIP Document {root='list'};

				

Return a standalone document

If we want to return a document as standalone (standalone="yes" in the header in case of XML) without validation, we have to declare this with explicit document meta data as RETURN SKIP {standalone='yes',root='root'}.


COMMAND process Document
	CALL doProcessDocument
	RETURN SKIP {standalone='yes',root='list'};

				

Explicit filter definitions for a command

For most processing it's enough to declare the standard filters in the configuration of the command handler. But in certain cases we want to declare a filter explicitly for a command, for example to preprocess a certain document type with an XSLT filter. Explicitly declared filters always refer to a document format and documents of other formats have to be converted first or they cannot be preprocessed. The conversions mechanisms we will explain in detail later. Explicit filter declarations are done with

  • FILTER <name> or

  • FILTER INPUT <inputfiltername> or

  • FILTER OUTPUT <outputfiltername> or

  • FILTER INPUT <inputfiltername> OUTPUT <outputfiltername>

Here is an example:


COMMAND process Document FILTER INPUT myXsltInputFilter
    CALL doProcessDocument RETURN Document;

				

Authorization checks

We can tag a command to be allowed only after an authorization check. The check denies command execution with an error if the login of the user does not allow the execution of the command. The call is the same as in TDL for example. Authorization checks are triggered by the AUTHORIZE attribute with one or two arguments as follows:

  • AUTHORIZE <authfunc> or

  • AUTHORIZE <authfunc> <resource>

Adding parameters from the execution context

Wolframe functions that are written in a language other than C++ are usually pure data in / data out functions. So the input document defines the input. But sometimes we need to include data from the user context into processing, for example for inserting or editing some personal data. Wolframe gives us the possibility to include data from the execution context into the input document. We do this with the directive CONTEXT followed by a list of comma ',' separated assignments in curly brackets '{' '}'. The following example adds an element 'uname' that does not exist yet in the input to the input document before execution (after validation). The value of the add 'uname' element is the user name of the user issuing the request.


COMMAND insert UserData CONTEXT { uname = UserName }
    CALL doInsertUserData;

				

This way we keep the processing functions as pure data functions. We are in certain cases able to inject some login dependent data in a controlled way, without exposing an API to all language bindings for being able to access everything from everywhere.

Using brackets

For better readability you can use optional '(' ')' brackets on the arguments of the command declaration:


COMMAND ( process Document )
    FILTER INPUT myXsltInputFilter CALL doProcessDocument
    RETURN Document;

				

Overview

Each command declaration has as already explained the form

  • COMMAND <doctype> [OPTIONS] ; or

  • COMMAND <action> <doctype> [OPTIONS] ;

The following table shows an overview of the elements that can be used in the [OPTIONS] part of the command:

Table 5.1. Options

KeywordsArgumentsDescription
CALLFunction NameNames the function to be called for processing the request
RETURNDocument TypeSpecifies the type of the document returned and forces validation of the output
RETURN SKIPDocument TypeSpecifies the type of the document returned but skips validation of the output
SKIP(no arguments)Specifies the input document validation to be skipped
FILTER INPUTFilter NameSpecifies that the filter <Name> should be used as input filter
FILTER OUTPUTFilter NameSpecifies that the filter <Name> should be used as output filter
FILTERFilter NameSpecifies that the filter <Name> should be used both as input and output filter
AUTHORIZEfunc resSpecifies that the function <func> should be called with the resource <res> to check if the user is allowed to execute the command.