Build apps

Using LinkedDataHub as a low-code platform for Knowledge Graph applications

Every component in LinkedDataHub is data-driven and was designed with extensibility in mind. You can override behavior (e.g. Java method or XSLT template) without having to modify LinkedDataHub's codebase, and more importantly, without having to write the same logic from scratch.

The following sections are split by component/layer and explain how to extend them when building bespoke apps.

Docker

You can go a long way just by mounting files (e.g. config files, ontologies, stylesheets) into LinkedDataHub's default Docker setup. But you may also want to build a dedicated Docker image for your app using LinkedDataHub as the base. Usually this is done to COPY files inside the image or RUN additional commands.

The recommended approach is a multi-stage Docker build: the first stage uses Maven to compile your WAR overlay, and the second stage copies it into the LinkedDataHub base image alongside any static files:

FROM maven:3.8.4-openjdk-17 AS maven

WORKDIR /usr/src/myapp

COPY src /usr/src/myapp/src
COPY pom.xml /usr/src/myapp/pom.xml

RUN mvn clean install

# =================

FROM atomgraph/linkeddatahub:5.3.2

WORKDIR $CATALINA_HOME

ENV SERVLET_NAME=com.example.myapp.Application

COPY --from=maven /usr/src/myapp/target/ROOT webapps/ROOT

COPY files/layout.xsl /usr/local/tomcat/webapps/ROOT/static/com/example/myapp/xsl/layout.xsl
COPY files/client.xsl /usr/local/tomcat/webapps/ROOT/static/com/example/myapp/xsl/client.xsl
COPY files/style.css  /usr/local/tomcat/webapps/ROOT/static/com/example/myapp/css/style.css

SERVLET_NAME must be set to the fully-qualified name of your JAX-RS application class (see the Java section below).

Java

The Java layer of LinkedDataHub is a Maven project with a webapp layout. The codebase uses JAX-RS, specifically Jersey 3, as the HTTP/REST framework and uses Apache Jena for RDF I/O.

If you want to extend the Java codebase, for example to add a custom REST endpoint, create a new Maven project (Java 17, packaged as WAR named ROOT) with LinkedDataHub as a WAR overlay dependency:

<dependencies>
    <dependency>
        <groupId>com.atomgraph</groupId>
        <artifactId>linkeddatahub</artifactId>
        <version>5.3.2</version>
        <classifier>classes</classifier>
    </dependency>
    <dependency>
        <groupId>com.atomgraph</groupId>
        <artifactId>linkeddatahub</artifactId>
        <version>5.3.2</version>
        <type>war</type>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <release>17</release>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <warName>ROOT</warName>
                <webappDirectory>target/ROOT</webappDirectory>
                <attachClasses>true</attachClasses>
                <overlays>
                    <overlay>
                        <groupId>com.atomgraph</groupId>
                        <artifactId>linkeddatahub</artifactId>
                    </overlay>
                </overlays>
            </configuration>
        </plugin>
    </plugins>
</build>

After adding a new endpoint, extend LinkedDataHub's JAX-RS application class (com.atomgraph.linkeddatahub.Application) and register your class there. Set the SERVLET_NAME Docker environment variable to the fully-qualified name of your subclass so LinkedDataHub loads it instead of the default application.

By convention, static files (e.g. stylesheets, images) are placed in the src/main/webapp/static/ folder in the codebase, which then becomes /usr/local/tomcat/webapps/ROOT/static/ within the webapp deployed in the Docker container, and is available as ${base}static/ over HTTP.

This means that if you want to deploy static files as part of your LinkedDataHub app, you will have to either mount them into the /usr/local/tomcat/webapps/ROOT/static/ folder in the container, or copy them into a custom Docker image to the same effect.

You can allow Java debugger access using configuration properties.

XSLT

LinkedDataHub uses XSLT 3.0 for UI rendering both on the server- and on the client-side.

You can specify a custom server-side XSLT 3.0 stylesheet in the dataspace configuration.

You can reuse LinkedDataHub's stylesheets by importing them as explained in the change layout user guide.

Server-side

The default server-side stylesheet layout.xsl and its imports can be found in the src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2 folder.

Client-side

Client-side stylesheets are used to implement the interactive parts of the UI (event handling, AJAX calls etc.) using the IXSL extension provided by the SaxonJS library. This way the frontend is made completely declarative and does not require almost any Javascript code, with exceptions of 3rd party libraries such as Google Charts and OpenLayers.

Client-side stylesheets share common document-, resource-, and property-level templates with the server-side stylesheets. The client-side stylesheet may not contain any XML entity declarations (limitation of SaxonJS) and must be compiled into a SEF file before it can be run by the SaxonJS runtime. By default, the URL of the client-side SEF stylesheet can be specified as the $client-stylesheet param of the document-level server-side xhtml:Script template.

RDF

You can modify or extend the default RDF datasets used by LinkedDataHub. However, a better practice is to use the CLI scripts to create documents and to import CSV and RDF data.

See the LinkedDataHub app repository for more examples.