Creating a Comunica project configuration

The Comunica engine is always instantiated using a configuration file. This files describes the components that should be loaded into the engine, and how they are wired.

In this tutorial, we cover the requirements for such a configuration and how to create one yourself. Examples can be found in the currently existing init actors, such as the configurations of actor-init-sparql.

Note

Although we call them configuration files, they are actually just a collection of RDF triples. This means that you can for example also use a Turtle file or an API that returns a set of N-Triples. All our examples will be in JSON-LD, as JSON is easier to use for non-RDF experts, but they can easily be replaced by other formats.

Note

Throughout this document, we reuse the terminology of Components.js where a component is a class that can be instantiated, and a module is a collection of components.

Note

These configuration files are Components.js configuration files. As such, the more advanced features from Components.js can be used here as well.

Runner

Every Comunica engine is started from a Runner. The Runner module is responsible for loading the modules from a configuration and wiring them. It is also responsible for sending the input actions to the actors listening to its Bus, which is the init Bus by default. All other actors are linked to the Runner as follows:

{
  "@context": [ 
    "https://linkedsoftwaredependencies.org/contexts/comunica-runner.jsonld",
    "https://linkedsoftwaredependencies.org/contexts/comunica-core.jsonld",
    ...
  ],
  "@graph": [
    {
      "@id": "urn:comunica:my",
      "@type": "Runner",
      "actors": [
          {
            "@id": "ex:myInitActor",
            "@type": "ActorThatInitializes"
          },
          {
            "@id": "ex:myRdfParserN3",
            "@type": "ActorRdfParseN3"
          },
          {
            "@id": "ex:myRdfParserJsonLd",
            "@type": "ActorRdfParseJsonLd",
            "priorityScale": 0.9
          },
          ...
      ]
}

All other actors must be contained in the actors array. At least one of these actors should be listening to the init bus, to receive the input actions and handle those.

Note

The context files are required to abbreviate the full URIs of components. For example, the first context can be used to write actors instead of https://linkedsoftwaredependencies.org/bundles/npm/@comunica/runner/actor.

Defining an Actor

The minimum requirement for having an Actor loaded by the Runner, is to define a component of a certain type, e.g.:

    {
      "@id": "ex:mySparqlParser",
      "@type": "ActorSparqlParseAlgebra"
    }

In this case an ActorSparqlParseAlgebra instance would be created, with the default settings of that class.

Note

While it is not required, the convention is to always add an @id to identify each Actor. This will make it easier to debug Runner loading failures or other errors that reference components.

Configuring an Actor

Next to just including including components, the configuration file can also be used to configure the parameters of an actor.

The following example configures the JSON serialization indentation of an ActorRdfSerializeJsonLd using the jsonStringifyIndentSpaces parameter.

    {
      "@id": "ex:myRdfSerializeJsonLd",
      "@type": "ActorRdfSerializeJsonLd",
      "jsonStringifyIndentSpaces": 2
    },

Let's take a more complex example from the default actor-init-sparql config.

  {
    "@id": "urn:comunica:sparqlinit",
    "@type": "ActorInitSparql",
    "mediatorQueryOperation": {
      "@id": "ex:mediatorQueryOperation",
      "@type": "MediatorRace",
      "cc:Mediator/bus": { "@id": "cbqo:Bus/QueryOperation" }
    }, ...
  }

Here you can see how the mediatorQueryOperation parameter of the ActorInitSparql Actor is defined, which is again a new type, MediatorRace, with its own parameters. Note that we can use mediatorQueryOperation instead of the full URI due to the context files again. Since this is JSON-LD, other actors that would need the same mediator can just reference it by its @id:

  {
    "@id": "ex:myUnionQueryOperator",
    "@type": "ActorQueryOperationUnion",
    "cbqo:mediatorQueryOperation": { "@id": "ex:mediatorQueryOperation" }
  }

Which references the same mediator ex:mediatorQueryOperation.

Configuring buses

Buses typically don't require a separate implementation. They can therefore directly be instantiated by the default Bus implementation.

Many Buses have already been pre-defined, such as the cbqo:Bus/QueryOperation Bus:

{
  "@context": "https://linkedsoftwaredependencies.org/contexts/comunica-bus-query-operation.jsonld",
  "@id": "cbqo:Bus/QueryOperation",
  "@type": "cc:Bus",
  "comment": "A comunica bus for query-operation events."
}

But which actors do I put in the configuration file now?

Well that is the beauty of Comunica: it is completely up to you! Besides the Runner, all other Actors are optional. So you should include all Actors that are necessary to solve your problem.

The easiest way is to start from existing configuration files and adapt those.

Note

The applicable buses will typically require at least one registered actor. If no actor can be found to solve a certain action, Comunica will also throw an error at runtime.