In the previous article, we illustrated FragLink, a framework for enabling Linked Data Fragments capabilities to your server application.
As said there, FragLink is not a server itself. Instead, it comes as an autoconfigure module that you can easily plug into your application.
Once FragLink is set up, everything related to Linked Data Fragments Web API is enabled (i.e., HTTP endpoint, metadata, controls): of course, the concrete data binding is up to you.
This article is a step-by-step guide that illustrates using FragLink to implement a Linked Data Fragments Server, specifically a Triple Pattern Server.
The (example) Domain Model
We have a project that stores its data in a relational database. The project deals with personal information about contacts of our customers; the domain model is simple (we kept it simple for this article)
We have a list of companies; for each, we store the corresponding contacts and their roles (e.g., customer representative, CEO, vendor).
Fortunately, our company is small, so the entire dataset is small. Here’s the contact at the time of writing:
XYZ Ltd
VAT: 00238238123
- Mr. Ken Smith, CEO, k.smith@xyz.org, +39200232383, +992392929
- Mrs. Dora Hug, Sales Director, d.hug@xyz.org, +39232888318, +999230132
- Mrs. Lyu Key, Customer Service, l.key@xyz.org, +39200245351, +9900203823
ABC SRL
VAT: 01648827372
- Mrs. Lia Dotti, CEO, lia.dotti@abc.it, +393628294745, +3908882382
- Mr. Giovanni Rossi, CTO, giovanni.rossi@abc.it, +3987663552, +39088882992
- Mr. Ugo Bianchi, Sales, ugo.bianchi@abc.it, +393857733645, +39088882765
JYY SRL
VAT: 02627717271
- Mr. John Doe, CEO, john.doe@jyy.com, +2382917337, +9832723728
- Mr. Johnatan Hellis, Sales, johnatan.hellis@jyy.com, +9283829838, +29382938
How to represent such a dataset?
Although there are several choices regarding ontologies for representing such a (small) dataset, we keep things simple: we will use FOAF and DC. Here’s our dataset in RDF:
Ken Smith
CEO
+39200232383 />
+992392929
CEO
Dora Hug
Sales Director
+39232888318
+999230132
Sales Director
Lyu Key
Customer Service
+39200245351
+9900203823
Customer Service
Lia Dotti
CEO
+393628294745
+3908882382
CEO
Giovanni Rossi
1977-03-10
CTO
+3987663552
+39088882992
CTO
...
XYZ Ltd
00238238123
ABC SRL
01648827372
JYY SRL
02627717271
So far, so good. We now need a SPARQL endpoint so clients, applications, and other entities can consume our data.
Linked Data API: Architecture
Here’s a diagram from the previous article:
We will rely on the open-source project Comunica as a Linked Data Fragment Client. In that context, it is in charge to
- expose the SPARQL endpoint
- receive the client’s queries
- execute the queries by distributing the compounding triple patterns across the available Linked Data Fragment servers
Our role is to implement the Linked Data Fragment Server using FragLink, an open-source framework.
The previous article and the FragLink repository describe the steps required to create a project skeleton. This post starts from there, specifically by implementing the Triple Pattern Resolver.
The Linked Data Fragment Resolver
To create a binding tied to a specific data source, you must create an implementation of
com.spaziocodice.labs.fraglink.service.impl.LinkedDataFragmentResolver
The interface contains a single method, which takes a triple/quad pattern as input and expects a list of matching triples as output. The FragLink framework uses Apache Jena, a powerful and open-source set of tools for dealing with RDF data.
So, our task is “simple”: we need to provide the implementation of that interface, and specifically for the method:
TriplePatternResponse linkedDataFragment(
Optional subject,
Optional predicate,
Optional object,
Optional graph,
Optional pageNumber,
HttpServletRequest request)
The Linked Data Client will send one or more triple pattern requests through that interface; the implementation should translate those requests into the matching triples (encapsulated in the TriplePatternResponse instance).
For example, a request like this:
?s foaf:name ?o
Should answer with all triples having a <foaf:name> as a predicate, regardless of the subject or the object. In our dataset, it should be something like this:
"Ken Smith" .
"Dora Hug" .
"Lyu Key" .
...
Talk is cheap, show me the code!
The example repository contains a linked data fragment server built on FragLink. Note that this example was built in one day; the purpose is to illustrate the power of producing real-time RDF data without having dedicated RDF storage.
The repository is a plain Springboot module that implements the Contact-Company scenario depicted above.
Data is stored in an “in-memory” H2 relational database (see the resources/data.sql file), which allows you to get up and running the demo without having to worry about databases and storage.
Two data access objects are in charge of extracting and translating the result of the query executions.
That’s it: apart from the extraction and translation logic, everything (e.g., metadata, controls) is managed by FragLink.
If you want to run the example, here’s what you need:
- Java 17 or higher
- Apache Maven 3.x
- Git
Step #1: Clone the repository, build the project
> git@github.com:spaziocodice/linked-data-fragment-server-example.git
> cd linked-data-fragment-server-example.git
> mvn clean install
You should see the following messages:
...
[INFO] Installing ... simple-ldf-server-1.0-SNAPSHOT.pom
[INFO] Installing ... simple-ldf-server-1.0-SNAPSHOT.jar
[INFO] --------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] --------------------------------------------------
[INFO] Total time: 1.429 s
[INFO] Finished at: 2024-04-24T20:14:09+02:00
[INFO] --------------------------------------------------
Step #2: Start the Linked Data Fragment Server
> cd target
> java -jar simple-ldf-server-1.0-SNAPSHOT.jar
You should see the following messages:
...
2024-04-24 ... : FragLink v2.0.0 has been enabled on this server.
2024-04-24 ... Started App in 2.706 seconds
Step #3: Experiment using some SPARQL query
We will use comunica.dev as a Linked Data Fragment Client. Open your favorite browser and point to https://query.comunica.dev/.
The user interface allows you to choose one dataset from a predefined list. You can also manually type the URL of a SPARQL endpoint. Make sure to type in that text field: https://127.0.0.1:8080/fragments (the endpoint of the server you just started in the previous step).
You’re ready. To begin, type a valid query in the text area below. Here are some example queries.
Example #1: Give me everything!
SELECT ?s ?p ?o
WHERE
{
?s ?p ?o .
}
Example #2: Give me everything about a customer
PREFIX customers:
SELECT ?p ?o
WHERE
{
customers:1 ?p ?o .
}
Example #3: Give me the customers (URI) and their role
PREFIX foaf:
PREFIX org:
SELECT ?s ?email ?role
WHERE
{
?s foaf:mbox ?email .
?s org:role ?role .
}
Example #4: Give me the customers (URI) and their company name
PREFIX foaf:
SELECT ?s ?companyName
WHERE
{
?s foaf:member ?o .
?o foaf:name ?companyName .
}
Remember: the repository is a simple example; I’m sure it contains a lot of redundancy and, if you start experimenting with other queries, a lot of issues, as well.
Let’s stay focused on the underlying concept: we have a plain relational database, and after implementing a straightforward interface (the triple pattern server contract), we have provided our data in RDF.
That opens many possibilities, including dynamic mappings or leveraging other types of storage (e.g., NoSQL).
Enjoy!
We would love to hear questions, doubts, and feedback about this blog post!
Feel free to contact us or leave a message in the comment box below.