Contents

    Introduction

    This document is an introduction to Elda, an implementation of the Linked Data API (LDA). The LDA allows you to have a configurable, REST-style interface to a store containing RDF data. This makes it easier for developers used to using common web technologies such as JavaScript and JSON to access your data, and display it in a web browser.

    Elda is a Java implementation of the LDA specification, and was developed by Epimorphics Ltd. Elda is licensed under an open-source Apache License.

    A quick introduction to running Elda

    Before we go on to explain more of what Elda is doing and how you can customise it, let’s get an instance of Elda running and see what it can do.

    The easiest route to starting Elda is to use the pre-packaged Java .jar file that you can download from http://repository.epimorphics.com/com/epimorphics/lda/elda-standalone/2.0.2/elda-standalone-2.0.2-exec-war.jar. You can start the file from the command line.

    java -jar elda-standalone-$VERSION-exec-war.jar
    

    where $VERSION denotes the version number of the Elda you downloaded, such as 2.0.2. If your system permits, double-clicking on the file in your preferred file browser may also work.

    At this point, you may see a large number of log messages as Elda starts, and then you should be able to view the starting page in a web browser: http://localhost:8080/standalone/again/games. This should display a page similar to:

    Screenshot showing demo dataset in
Elda

    What just happened?

    Contained within the standalone Elda version is a small RDF dataset about board games. The example configuration provides an API for viewing the contents of this dataset through simple web URLs. http://localhost:8080/standalone/hello/games lists the first page of board games that are in the example data.

    By default, the list is presented in HTML format, which is nice for people to read, but not so good for programs to process. The data format pulldown on the top-right of the page are clickable to select a different format, eg by clicking the ttl link, the BoardGame resources will be shown as RDF Turtle.

    The pull-down menus also allow you to go to a selected item, to adjust the page size and which page to view, or to change the view (which properties to show) of the data.

    How did it happen?

    When Elda is presented with a URL, it uses it to select an endpoint. From the details of the URL path (/games in this case) and its query parameters (none in this case), it constructs a SPARQL query which selects one or more items (here, games) from the RDF dataset. It then constructs a view of (some of the) properties of those items, and then renders that view into one of the possible formats, sending that rendering back to whatever sent the query.

    This example displays all available properties.

    Decisions about which datasets to display, which end-points ( ie, URL patterns) display which resources, how resources are displayed, and other design choices are all encoded in the LDA configuration file. The LDA specification describes in detail what goes in a configuration file. The configuration file itself uses RDF to encode these configuration choices, and is typically written in the Turtle syntax, as it is relatively readable and compact. Elda comes with various pre-built examples which may help you to get started with building your own specs. Ultimately, it is the configuration file which specifies how Elda URLs are turned into queries against the underlying store, and how the results of those queries are presented back to your users.

    The cribsheet gives a terse overview of the meaning of the LDA query parameters and configuration properties.

    Summary of LDA capabilities

    Tutorial

    We will now work through some of Elda’s capabilities in slightly more detail. See the reference page for more comprehensive and detailed descriptions.

    Prerequisites

    Elda is written in Java (using the Jena RDF toolkit), so you will need Java installed on your system.

    The default demonstration setup for Elda has examples that use the data.gov.uk data accessible from the SPARQL endpoint http://education.data.gov.uk/sparql/education/query. To run those examples, you will need to have open web access.

    Downloading and starting Elda

    There are two ways to get Elda: either by downloading the pre-compiled runnable demo .jar file, or by checking out the source code from its GitHub project and then compiling the Java source.

    The runnable .jar can be downloaded from http://repository.epimorphics.com/com/epimorphics/lda/elda-standalone and following through to a recent version, or the version current for this page: elda-standalone-1.3.0.jar.

    If you want to explore the Elda code and have git installed, you can copy the Elda repository:

    git clone https://github.com/epimorphics/elda.git
    

    To compile the code, you will also need Apache Maven:

    mvn clean package
    

    After compiling, the runnable .jar file will be in ./elda-standalone/target/elda-standalone-$VERSION-exec-war.jar.

    If you can’t use port 8080

    Your computer may already be using port 8080 for some other service. In that case, you can start Elda from the command line (this won’t work when double-clicking in a file manager) with:

    java -jar standalone.jar -httpPort NNNN
    

    Built-in example datasets and configurations

    Elda comes pre-packaged with some example configurations and an example dataset. The sample URLs in the table below should all work if you have Elda running on your local computer, on port 8080:

    description

    config file

    sample URLs

    one-template games example, local SPARQL endpoint.

    hello-world.ttl

    standalone/hello/games

    standalone/hello/games.xml

    two-template games example, local SPARQL endpoint.

    hello-again-world.ttl

    standalone/again/games

    standalone/again/publishers

    standalone/again/publishers.json

    one-template education example, external SPARQL endpoint.

    tiny-education.ttl

    standalone/tiny/doc/school

    multi-template education example, external SPARQL endpoint.

    mini-education.ttl

    standalone/mini/doc/school

    standalone/mini/doc/school/phase/primary

    standalone/mini/doc/school/100855

    full education example, external SPARQL endpoint.

    full-education.ttl

    standalone/full/doc/school

    standalone/full/def

    standalone/full/def/school

    standalone/full/doc/school?max-schoolCapacity=100

    old education example [for comparison], external SPARQ endpoint.

    old-education.ttl

    standalone/old/education/schools/primary

    old/education/schools?label=Hope+Primary+School

    Games example – web page

    Let’s look a little at the two-template games example, standalone/again.

    (Refer to the cribsheet for a summary of the action of Elda’s query parameters.)

    The page http://localhost:8080/standalone/again/games shows us the properties (as in the example data file) of several boardgames. This HTML view allows you to explore the dataset. For example, A Brief History of the World has publication date 2009. Clicking the dropdown icon on that line restricts the results to only those with that publication date – the Brief History and Last Train to Wensleydale(. And we see (from the URL bar) that the URL of this page has had a *publicationDate=2009 query parameter added.

    The dropdown menu also allows you to select games whose publication date is the same as, or less recent than, A Brief History of the World, or, separately, no older. In both cases, the URL changes to show the applied filter. Selected options can be de-selected.

    Similarly you can play with the value of players, eg restricting the number to 4 will show only games that have a 4-player option (not that it does not reject games that allow other numbers of players). And you can apply more than one filter, perhaps asking for seven-player games from before 2005.

    You can also chose to sort according to the selected property or properties, eg by publication date or (rough) play time in minutes, or both. However, players, being multi-valued, isn’t really a good sorting candidate.

    Games example – configuration

    We’ll talk briefly through the LDA specification used for the games example.

    #
    # A hello-world config.
    #
    
    # Assorted prefix declarations. Some of them are for the structuring
    # of the API config, others are for the vocabulary definitions.
    #
    
    @prefix api:    <http://purl.org/linked-data/api/vocab#> .
    @prefix dct:    <http://purl.org/dc/terms/> .
    
    @prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    @prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
    @prefix xsd:    <http://www.w3.org/2001/XMLSchema#> .
    
    # The elda namespace/prefix is for Elda extensions to the LDA specification.
    @prefix elda:   <http://www.epimorphics.com/vocabularies/lda#> .
    
    # Prefix for example-local entities.
    @prefix hello:  <http://localhost:8080/elda/vocabulary/>.
    

    The prefixes declared here make the configuration more concise and are used in the result model from the LDA query.

    # ---------------------------------------------------------------------
    # API config
    
    hello:hello-world-again a api:API
    ; rdfs:label "Hello World example #2 -- games"@en
    

    hello:hello-world-again is declared as an API. The label is used as a title in /api-config.

    # Name the SPARQL endpoint which supplies the data we present
    ; api:sparqlEndpoint <local:data/example-data.ttl>
    

    The SPARQL endpoint for this API is a local file. (This is an Elda extension to the LDA for testing and demonstration purposes.)

    ; api:defaultViewer api:labelledDescribeViewer
    

    The default view for this API is the built-in labelledDescribeViewer, which fetches all the properties of the item using a SPARQL DESCRIBE and also fetches the labels of all the resource values this finds.

    ; api:viewer [a api:Viewer; api:name "none"; api:properties ""]
    

    This defines a new view called none which shows no properties at all. This can be useful as a starting-point when building a view on the URL using the query parameter _properties=.

    ; api:variable
      [ api:name "_resourceRoot"
      ; api:value "http://localhost:8080/standalone/lda-assets/"
      ]
    

    The special variable _resourceRoot is used by Elda as the base URI for assets needed for the HTML rendering of results.

    ; api:endpoint
      hello:publishers, hello:games
    

    These are two endpoints for this API, hello:games and hello:publishers.

    ; api:formatter
      [ a api:VelocityFormatter
      ; api:name "html"
      ; api:mimeType "text/html; charset=utf-8"
      ]
      .
    

    (An alternative (older) formatter which generates its results using XSLT stylesheets, is also available.)

    # Endpoint definitions
    
    hello:publishers a api:ListEndpoint
      ; rdfs:label "Publishers"
      ; api:uriTemplate "/publishers"
      ; api:selector [api:filter "type=Publisher"; api:sort "label"]
      ; api:defaultViewer api:labelledDescribeViewer
      .
    

    This is the publishers endpoint. It will show only items of type hello:Publisher, sort them by their label (which will be the publisher name), and view them with the labelledDescribe viewer.

    hello:games a api:ListEndpoint
      ; rdfs:label "Games"
      ; api:uriTemplate "/games"
      ; api:selector [api:filter "type=BoardGame"; api:sort "label"]
      ; api:defaultViewer api:labelledDescribeViewer
      .
    

    Similarly, this is the games endpoint, selecting only items of type hello:BoardGame and sorting them by their label.

    The rest of the configuration defines property and class shortnames and other important attributes. The resouces (classes and properties both) that are of interest are those of type rdf:Property, owl:ObjectProperty, owl:DatatypeProperty, rdfs:Class, and owl:Class.

    hello:BoardGame a rdfs:Class
    ; rdfs:label "Board Game"
    ; api:label "BoardGame"
    .
    

    The class hello:BoardGame has shortname BoardGame, as defined by its api:label; this is what allows it to appear in the endpoint filter type=BoardGame.

    hello:players a rdf:Property
    ; api:label "players"
    ; rdfs:range xsd:int
    .
    

    hello:players has shortname players, which is what allows you to use eg players as the name of a query parameter. Defining its range to be xsd:int means eg that the 2 in the query parameter players=2 is interpreted as an integer and not a string.

    hello:Publisher a rdfs:Class
      ; api:label "Publisher"
      .
    

    Similarly to BoardGame.

    dct:publisher a rdf:Property
      ; api:label "publishes"
      .
    

    Declares that the shortname of dct:publisher is publishes.

    rdfs:label a rdf:Property
      ; api:multiValued true
      ; api:label "label"
      .
    

    Declares that rdfs:label has shortname label and that it is always to be presented in the JSON rendering as having an array of label values, even if there’s only one.

    rdf:type a rdf:Property
      ; api:multiValued true
      ; rdfs:range rdfs:Class
      ; api:label "type"
      .
    

    Declares that rdf:type has shortname type, should have its JSON-rendered values appear as an array, and has a range of rdfs:Class, which means that for a query parameter type=SPOO, SPOO is interpreted as being the shortname of some resource rather than a literal string.

    hello:designed-by a rdf:Property
      ; api:label "designedBy"
      .
    

    Declares that hello:designed-by has shortname designedBy. (Note that the HTML renderer shows property shortnamesin the display translated by turning camelCase like designedBy into space-separated words like designed by.)

    hello:designer-of a rdf:Property
      ; api:label "designerOf"
      .
    

    The shortname of hello:designer-of is designerOf.

    hello:pubDate a rdf:Property
      ; api:label "publicationDate"
      ; rdfs:range xsd:integer
      .
    

    And finally, the shortname of hello:pubDate is publicationDate and its value is interpreted as an integer.

    That concludes our example LDA specification. For more details on LDA configurations, see the Linked Data API (LDA) and the Elda reference material. Also see the other API configurations mentioned above.

    Using other LDA specifications

    From the command line

    To use different LDA specifications, use the system property elda.spec. Like the port number, it can be set as part of launching the elda jar or when launching the jetty start jar:

    java -jar standalone.jar -Delda.spec=SPECS
    

    If you use elda.spec, then Elda ignores the default specification (the education LDA) wired into it.

    By editing web.xml

    To change the specification used without having to use a -Delda.spec command line option every time, you will have to build your own version of Elda; see the instructions elsewhere (TBD). When you do so, edit webapps/elda/WEB-INF/web.xml. Find the servlet configuration

    <servlet>
      <servlet-name>loader-init</servlet-name>
      <servlet-class>com.epimorphics.lda.routing.Loader</servlet-class>
      <init-param>
        <param-name>com.epimorphics.api.initialSpecFile</param-name>
        <param-value>assorted specs here</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
    </servlet>
    

    and replace the assorted specs here with the name of the LDA specification files you wish to load, separated by commas. Spaces and newlines are ignored. (For more explanation of the structure of the web.xml file, see the reference documentation).

    Older XSLT formatter

    To use the older XSLT renderer (typically if you have existing editing stylesheets or prefer the older rendering style), define an xslt formatter:

    api:formatter
      [a api:XsltFormatter
      ; api:name 'html'
      ; api:stylesheet 'xslt/result-osm.xsl'
      ; api:mimeType 'text/html'
    ]
    

    to your API root in your configuration file and arrange that the webapps/elda directory contents are served as static files.

    Alternative data sources

    Querying a local file

    If the remote SPARQL endpoint is slow, not yet fully configured, or plain unimplemented, you might want to set up a local endpoint using a tool like Fuseki. But it’s also possible for Elda to query a local RDF file.

    Edit your spec file, which will look something like the education spec suplied with Elda:

    spec:api
      a api:API ;
      rdfs:label "Edubase API"@en;
      api:maxPageSize 50;
      api:defaultPageSize 10 ;
      api:sparqlEndpoint <http://education.data.gov.uk/sparql/education/query> ;
      api:endpoint
       spec:schools
       , spec:schoolsPrimary
       , spec:schoolsSecondary
       , spec:schoolsPrimaryDistrict
       , spec:schoolsSecondaryDistrict
     .
    

    Replace the endpoint URI with local:content-name, where content-name is the name of the RDF source you wish to query. When Elda issues queries to a local: endpoint, it loads (and remembers) the contents and queries those directly.

    Usually the content-name is a file name. It is resolved against the webapps context path (ie the directory from which it serves files). If there is no such file, then the content-name is treated as a URL and its contents fetched. If that fails, then the content is searched for along the webapps classpath. In all of these cases, the fetched content is loaded into memory as an RDF model and all queries to the endpoint are answered by this model.

    (The name-lookup functionality is supplied by the underlying Jena FileManager class; for more details, see the Jena documentation currently at openjena.org.)

    Using a local TDB datasource [obsolescent]

    As an alternative to setting up a local SPARQL endpoint, or using a local: file, you can instead use a local Jena TDB database. To do so you will need to modify the web.xml webapp configuration file and supply an additional init-param for the loader-init servlet. You can do this in two ways:

    <init-param>
      <param-name>com.epimorphics.api.TDB-base-directory</param-name>
      <param-value>tdb-directory</param-value>
    </init-param>
    

    Replace tdb-directory with the path to your chosen TDB directory. Note that the path is relative to the webapps directory – your best choice is to use an absolute path.

    Warning. If the directory does not contain any TDB files, TDB will create a new empty dataset in it. This is usually not what you want, since all queries will return no answers, so Elda will report an error during setup.

    The alternative form:

    <init-param>
      <param-name>com.epimorphics.api.dataStoreDirectory</param-name>
      <param-value>datastore-directory</param-value>
    </init-param>
    

    specifies datastore-directory as a directory containing a TDB directory named tdb. The same warnings as above apply. (This form exists because Elda can do limited LARQ indexing and in that case the datastore directory will have a larq subdirectory for the LARQ indexes.)

    Having specified a TDB directory, you can now edit your spec’s sparqlEndpoint declaration, which in the education example looks like:

    spec:api
      a api:API ;
      rdfs:label "Edubase API"@en;
      api:maxPageSize 50;
      api:defaultPageSize 10 ;
      api:sparqlEndpoint <http://services.data.gov.uk/education/sparql> ;
      api:endpoint
       spec:schools
       , spec:schoolsPrimary
       , spec:schoolsSecondary
       , spec:schoolsPrimaryDistrict
       , spec:schoolsSecondaryDistrict
     .
    

    Replace the services URI with tdb:model-name, where model-name is the name of your endpoint model inside the TDB store.

    Notes

    Feedback

    Elda aims to provide a complete implementation of the Linked Data API. Problems with Elda should be reported to the linked data API discussion group (note: you will need a google account to use this group).

    Current issues can be seen on the Elda issues list.