Author image SADI Framework
and 1 contributors


    SADI::Simple - Module for creating Perl SADI services.


The following code is a complete implementation of a 'Hello, World!' SADI service as a Perl CGI script.

    package HelloWorld;

    use strict;
    use warnings;
    use Log::Log4perl qw(:easy);
    use base 'SADI::Simple::AsyncService'; # or 'SADI::Simple::SyncService'
    my $config = {
        ServiceName => 'HelloWorld',
        Description => 'A \'Hello, World!\' service',
        InputClass => '',
        OutputClass => '',   
        Authority => '', 
        URL => '', 
        Provider => '',
        ServiceType => '',
        Authoritative => 0,
        NanoPublisher => 1,
    my $service = HelloWorld->new(%$config);
    use RDF::Trine::Node::Resource;
    use RDF::Trine::Node::Literal;
    use RDF::Trine::Statement;
    use Log::Log4perl;
    =head2 process_it
     Function: implements the business logic of a SADI service
     Args    : $inputs - ref to an array of RDF::Trine::Node::Resource
               $input_model - an RDF::Trine::Model containing the input RDF data
               $output_model - an RDF::Trine::Model containing the output RDF data
     Returns : nothing (service output is stored in $output_model)
    sub process_it {
        my ($self, $inputs, $input_model, $output_model) = @_;
        my $name_property = RDF::Trine::Node::Resource->new('');
        my $greeting_property = RDF::Trine::Node::Resource->new('');
        foreach my $input (@$inputs) {
            INFO(sprintf('processing input %s', $input->uri));
            my ($name) = $input_model->objects($input, $name_property);
            if (!$name || !$name->is_literal) {
                WARN('skipping input %s, doesn\'t have a <%s> property with a literal value');
            my $greeting = sprintf("Hello, '%s'!", $name->value);
            my $greeting_literal = RDF::Trine::Node::Literal->new($greeting);
            my $statement = RDF::Trine::Statement->new($input, $greeting_property, $greeting_literal);
            $output_model->add_statement($statement, $input);  # this second parameter is required for NanoPublishing
            # every statement added to the output model must include $input as the second parameter
            # in order for all of the statements to be in the same Assertion graph
            # $output_model->add_statement($statement); # non nanopublishers may omit the second parameter
                # if you are a NanoPublisher then add this line, at the end of the @inputs loop
                # it will be ignored for non-nanopublishers (i.e. optional)


This module provides classes for implementing SADI services in Perl. SADI (Semantic Automated Discovery and Integration) is a standard for implementing Web services that natively consume and generate RDF.

Key points of SADI standard:

  • A SADI service consumes a single RDF document as input and generates a single RDF document as output. The input RDF document may contain multiple input instances (i.e. graphs) representing separate invocations of the service.

  • A SADI service is invoked by an HTTP POST to the service URL, using an RDF document as the POSTDATA.

  • The structure of the input/output instances for a SADI service are described using OWL. The service provider publishes one input OWL class and one output OWL class which describe the structure of an input instance and an output instance, respectively.

  • Metadata for a SADI service is retrieved by an HTTP GET on the service URL. This metadata includes the URIs of the input and output OWL classes, as well as other information such as the service name, service description, etc.

The main strengths of SADI are:

  • No framework-specific messaging formats or ontologies are required for using SADI.

  • SADI supports processing multiple inputs in a single request, i.e. batch processing.

  • SADI supports long-running services, i.e. asynchronous services.

For more information about the SADI standard, see


Service providers may implement their SADI services as a subclass of either:


A service that subclasses SADI::Simple::SyncService is a synchronous service, which means that the service completes its computation before returning any response to the caller.


A service that subclasses SADI::Simple::AsyncService is a an asynchronous service, which means that the service returns an immediate "ask me later" response to a request, and must be polled for the results.

In general, asynchronous services are a better choice as they can run for an arbitarily long time. The main advantage of synchronous services is that there is less back-and-forth messaging and so they are potentially more efficient for services that perform trivial operations.

Service Configuration Parameters

Required parameters:


A human-readable name for your service.


A plain text description of your service.


The URI of the service's input OWL class. The input OWL class describes the required properties (i.e. predicates) of each input RDF node. In the example of the SYNOPSIS, there is one required property (


The URI of the service's output OWL class. The output OWL class describes the properties (i.e. predicates) that are attached each input RDF node, as a result of the service's computation. In the example of the SYNOPSIS, there is one attached property (


The hostname of the organization providing the service (e.g.


The contact email address of the service provider, in case of questions / problems.

Optional parameters:


The URL used to access your service. It is necessary to provide this parameter if the service is asynchronous and sits behind proxies/redirects, to ensure that the polling URLs returned by the service are publicly accessible.


A URI indicating the type of service. Ideally, this URI should come from a public ontology of service types, such as the "/ myGrid ontology" in http: for bioinformatics services. Specifying this parameter can potentially help other SADI users find your service.