Comunica Tutorial - Advanced

Ruben Taelman, Joachim Van Herwegen

Portorož, Slovenia, 3 June 2019

Comunica Tutorial - Advanced

Ghent University – imec – IDLab, Belgium

Tutorial Website:

A query engine is like a car

They both have swappable components

Hard-wiring of components

The easiest way to add components is by manually adding instances.

    const myCar = new Car();
    myCar.add(new EngineV8());
    myCar.add(new TireMichelin());
    myCar.add(new TireMichelin());
    myCar.add(new TireMichelin());
    myCar.add(new TireMichelin());

Downside: swapping components requires code changes.

Soft-wiring of components

Dependency Injection: Components are supplied by something external.

Components can be defined declaratively via a configuration file.

Comunica heavily makes use of dependency injection

Components.js: A dependency injection framework for JavaScript

Components are described in a semantic configuration file

→ A semantic layer on top of your source code

→ Configuration files could also be used for other programming languages

Comunica uses Components.js to wire actors, buses and mediators

Components.js Terminology

Module: Collection of components (e.g., a software package)

Component: Something that can be instantiated (e.g., a class)

Instance: An instantiated Component

A Module file describes a Module
and its Components


Comunica offers modules
for different query operators

Each module is published as a separate NPM package.

Each module is described in JSON-LD

We use import statements to refer to components in different files.

  "@context": …,
  "@id": "npmd:@comunica/actor-query-operation-distinct-hash",
  "@type": "Module",
  "requireName": "@comunica/actor-query-operation-distinct-hash",
  "import": [

Components are described in JSON-LD

  "components": [
      "@id": "Actor/QueryOperation/DistinctHash",
      "requireElement": "ActorQueryOperationDistinctHash",
      "parameters": [
          "@id":     "hashAlgorithm",
          "default": "sha1"
          "@id":     "digestAlgorithm",
          "default": "base64"


Components.js supports any kind of RDF serialization: Turtle, N-Triples, ...

For developers that are familiar with JSON

To achieve semantic RDF-based configurations:

The benefits of dereferencing

Modules, components and instances have a unique URL.

Others can reuse them by simply linking to them → distributed config files

Fetch them from anywhere (browser, query engine, ...)

npmd:@comunica/actor-query-operation-distinct-hash expands to

A Config file instantiates components

Comunica describes instances in JSON-LD

  "@context": …,
  "@id": "urn:comunica:my",
  "actors": [
      "@id":                    "#myDistinctQueryOperator",
      "@type":                  "ActorQueryOperationDistinctHash",
      "hashAlgorithm":          "RSA-SHA256"
      "@id":                    "#myConstructQueryOperator",
      "@type":                  "ActorQueryOperationConstruct"

Hands-on: creating a Comunica actor

Goal: Implementing, configuring, and using a custom REDUCED actor.

Hands-on: requirements

Hands-on: five steps

  1. Initialization of a Comunica engine: We provide an NPM package to start from.
  2. Creation of a new actor: JavaScript stub and module files.
  3. Actor configuration: Plugging in the actor via the config file.
  4. Logging configuration: Adding an existing logger to the config file.
  5. REDUCED implementation: Actual JavaScript implementation.

Each step can be skipped by checking out a different git tag.
For example, show the solution of step 2: git checkout tutorial-step/2