SOSS

Introduction

SOSS is an implementation of a SOAP server for OCaml.

It is designed to allow a service, developed in OCaml, to be made available as a SOAP service with minimal effort.

It's features include:

It is possible to write a series of service functions in pure OCaml without regard to SOAP and, from the interface file for the service automatically generate all that is required to reveal the service as a SOAP service through HTTP or TCP.

It is not, however, a completely general SOAP server. It's goal is as above, to define an OCaml service and reveal it as a SOAP service. As such it provides no support for more general SOAP features, such as SOAP with attachments.

New release

Version 0.1.03 has been released.

Main changes since 0.1:

Note!

Documentation on this site is always more up to date than that in the current release.

There is a bug in the version 0.1 implementation of genInterface (not the current release). genInterface will currently state that it requires specification of OutputAppModule. To work around this bug, please change the line
GenApp=true
in the default configuration file to
GenApp=false

Contact

I am very keen to make this a useful library for OCaml developers, so please, if you have any questions or problems with the library, don't hesitate to contact me:
stefanlampe at hotmail.com

Download

Latest version (0.1.03)

Version 0.1

Documentation

API documentation

Installation

SOSS requires a few things to be installed before it itself can be installed. SOSS has only been tested on linux.

Utilities it requires:

All utilities should be in the path

Libraries it requires:

All libraries should be locatable through the ocamlfind utility.

SOSS has been tested with these versions of the utilities and libraries:

For the example service it requires: It is recommended that these be installed as the example provides a test that everything is working properly and shows how to create an end to end application

If all of these are installed, cd to the root directory of the unpacked archive and run 'omake'

The soss library is in the lib directory
The interface generator, genInterface is in the bin directory
The example is in the bin/example directory

This installation procedure has not been thoroughly tested, if there are any issues, tell me (stefanlampe at hotmail.com), and I'll try to address them quickly.

Getting Started

An example is provided with the installation, a simple calculator service has been written to show the principles of the SOSS system.

Briefly, a service is simply an interface file for a module. In the interface are the types and functions that can be called remotely.

Once this module and interface has been created, a utility, genInterface, is used to create mapping code for the types and SOAP messages.

A short application module must be written. This does three things:

An example application module is provided to copy from.

That's it! Compile and link and the SOAP server can be run.

Definition of a SOAP service

The OCaml SOAP service is defined, as far as SOSS is concerned, with an interface file. This details the types and functions to be made available in the SOAP service. As such there are restrictions on the generality of the interface.

The first restriction is that types must be fully defined. There can be no types that take type parameters. References to types in other files cannot be made, the definition must be in the interface.

A list of the limitations on types is:
ignores parameterised types, exceptions, type aliases, types accessing other modules, function types, class types, labelled types, optional labelled types, object types, polymorphic types, variant types (though concrete types are supported)

The second restriction is on the function declarations. Types must be specified completely, and each type must be a type identifier. It is not possible to have a function such as
val f : string list -> int option

This must be changed to
type stringList of string list type intOpt of int option val f : stringList -> intOpt

Labelled parameters are supported, but optional types are not.

Once the interface has been defined it is possible to generate automatically all the code required using the genInterface tool supplied in the install. (SOSS_INSTALL/bin/genInterface.opt)

Use of genInterface

The files generated by genInterface consist of:

The interface module

It is not truly necessary to understand the representation that SOSS uses for XML data, but only to understand that conversion routines must be generated to translate between XML values and OCaml values. These routines are generated in the interface module.

The XML schema

The XML schema defines types for the XML values transferred in the use of the SOAP service. This file is also necessary for test the validity of the WSDL files.

WSDL files

These define the service in a WSDL file. 2.0 support can only be tentative as the specification is not yet finalised. It should be possible to generate client code in another language from the WSDL files produced.

In fact, the example does just this using Java and Axis to generate a lot of the client code.

Configuration options

There are a number of configuration options necessary to generate all the files above. To specify these options, a configuration file is used. The genInterface application can supply a default configuration file that shows the available options and gives a brief explanation of them. To obtain this, run the following command in the directory containing the OCaml service interface file:
genInterface -gen_config

This will create a genInterface.conf file. Examine this file and set the options required. Note that it is not necessary to generate all the files that are possible to generate and that some options are not required for all files. The genInterface utility will alert you if an option has not been set which should have been set.

When genInterface is run, the source for the interface and application will be generated in the current working directory. It is now possible to build the service.

Building the service

SOSS uses Ocamlduce to a large extent.

It is often possible to avoid compiling your service with OCamlduce, however.

The only case where this is not immediately possible is when the service generates SOAP faults. In this case the service must be compiled with OCamlduce, with reference to the soss library.

If it is necessary to compile with OCaml, it may be possible to move the error generation to a separate module. (i.e. create a module specifically for generating the SOAP faults from your service, that the rest of the service calls. Compile that module with OCamlduce. Then, it should be possible to compile the rest of the service with OCaml).

Whether or not the service is compiled with OCamlduce, it is always necessary to link with it.

It is assumed then that the build consists of a number of units:

The SOSS library doesn't rely on any other of these units, so it may be placed first in the build. (It is possible the service modules do rely on the SOSS library as it can generate SOSS faults). The service modules don't depend on the interface or the application, so it can be placed second in the build. The interface comes next, and finally, the application.
ocamlducec <soss lib> <service modules> <service interface> <service app>

The SOAP server can now be run.

An overview of the SOSS modules

The SOSS SOAP server comprises a number of separate modules.

The first, the front end, is the server - HTTP or TCP. These are minimal servers that collect requests and return responses. When setting up the SOSS system, the module required can be specified.

Both these servers can accept multiple connections, and process multiple connections at one time. However, if multiple requests are received through the one connection, they are not processed concurrently, but sequentially. This is because there is no information in the SOAP messages to indicate that the response belongs to a particular request. So the first request in leads to the first response out.

SOAP over HTTP is a standard way to present a SOAP service. TCP is not so standard. It is not possible to indicate the end of a SOAP message without doing at least a minimum of parsing of the data being received. As such the TCP server relies on the SOAP message being terminated with a zero byte of data. It is important to remember this if building a client connecting to the service over TCP.

When a request is received, it is passed to the SOAP handler. There are two SOAP handlers available, a single-threaded handler and a multi-threaded handler. The single threaded handler processes all requests sequentially, in the one thread. This ensures that the service is never exposed to more than one thread of execution at a time. If the service is thread safe, however, it is possible to allow each request received to execute in its own thread by using the multi-threaded handler.

Errors

The only case where the service code may need to be aware of the SOSS library surrounding it is in the case of errors. Most SOAP errors are handled by the SOSS library and the generated interface code. However, it is possible to generate a SOAP error from within the service by raising a SoapFault. Please look at the API documentation for more information on these faults.

Setting up the SOAP server

The function to use is SoapService.startService. This requires four parameters, an indication of the server type (tcp or http), the type of soap handler (single threaded or multi threaded) a 'registerService' function, and a port to run the server on.

The registerService function is part of the generated interface. If the interface module is called 'IntfModule', the registerService function is
IntfModule.registerService

The function returns the service. This can be passed to
SoapService.stopService
to stop the server. It will try to stop politely, after current requests have completed.