Skip to main content

SpazioCodice

Seamless RDF Data Querying FragLink-Driven Linked Data Fragments Servers

Seamless RDF Data Querying: FragLink-Driven Linked Data Fragments Servers

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: 

				
					<rdf:RDF 
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    xmlns:foaf="http://xmlns.com/foaf/0.1/"
    xmlns:org="http://www.w3.org/ns/org#">
  
  <foaf:Person rdf:about="https://spaziocodice.com/people/KenSmith">
    <foaf:name>Ken Smith</foaf:name>
    <foaf:title>CEO</foaf:title>
    <foaf:mbox rdf:resource="mailto:k.smith@xyz.org"/>
    <foaf:phone>+39200232383</foaf:phone>/>
    <foaf:phone>+992392929</foaf:phone>
    <org:role>CEO</org:role>
  </foaf:Person>

  <foaf:Person rdf:about="https://spaziocodice.com/people/DoraHug">
    <foaf:name>Dora Hug</foaf:name>
    <foaf:title>Sales Director</foaf:title>
    <foaf:mbox rdf:resource="mailto:d.hug@xyz.org"/>
    <foaf:phone>+39232888318</foaf:phone>
    <foaf:phone>+999230132</foaf:phone>
    <org:role>Sales Director</org:role>
  </foaf:Person>

  <foaf:Person rdf:about="https://spaziocodice.com/people/LyuKey">
    <foaf:name>Lyu Key</foaf:name>
    <foaf:title>Customer Service</foaf:title>
    <foaf:mbox rdf:resource="mailto:l.key@xyz.org"/>
    <foaf:phone>+39200245351</foaf:phone>
    <foaf:phone>+9900203823</foaf:phone>
    <org:role>Customer Service</org:role>
  </foaf:Person>

  <foaf:Person rdf:about="https://spaziocodice.com/people/LiaDotti">
    <foaf:name>Lia Dotti</foaf:name>
    <foaf:title>CEO</foaf:title>
    <foaf:mbox rdf:resource="mailto:lia.dotti@abc.it"/>
    <foaf:phone>+393628294745</foaf:phone>
    <foaf:phone>+3908882382</foaf:phone>
    <org:role>CEO</org:role>
  </foaf:Person>

  <foaf:Person rdf:about="https://spaziocodice.com/people/GiovanniRossi">
    <foaf:name>Giovanni Rossi</foaf:name>
    <foaf:birthday>1977-03-10</foaf:birthday>
    <foaf:title>CTO</foaf:title>
    <foaf:mbox rdf:resource="mailto:giovanni.rossi@abc.it"/>
    <foaf:phone>+3987663552</foaf:phone>
    <foaf:phone>+39088882992</foaf:phone>
    <org:role>CTO</org:role>
  </foaf:Person>

  ...
  
  <foaf:Organization rdf:about="https://spaziocodice.com/organizations/XYZLtd">
    <foaf:name>XYZ Ltd</foaf:name>
    <foaf:vat>00238238123</foaf:vat>
    <foaf:member rdf:resource="https://spaziocodice.com/people/KenSmith"/>
    <foaf:member rdf:resource="https://spaziocodice.com/people/DoraHug"/>
    <foaf:member rdf:resource="https://spaziocodice.com/people/LyuKey"/>
  </foaf:Organization>

  <foaf:Organization rdf:about="https://spaziocodice.com/organizations/ABCSRL">
    <foaf:name>ABC SRL</foaf:name>
    <foaf:vat>01648827372</foaf:vat>
    <foaf:member rdf:resource="https://spaziocodice.com/people/LiaDotti"/>
    <foaf:member rdf:resource="https://spaziocodice.com/people/GiovanniRossi"/>
    <foaf:member rdf:resource="https://spaziocodice.com/people/UgoBianchi"/>
  </foaf:Organization>

  <foaf:Organization rdf:about="https://spaziocodice.com/organizations/JYYSRL">
    <foaf:name>JYY SRL</foaf:name>
    <foaf:vat>02627717271</foaf:vat>
    <foaf:member rdf:resource="https://spaziocodice.com/people/JohnDoe"/>
    <foaf:member rdf:resource="https://spaziocodice.com/people/JohnatanHellis"/>
  </foaf:Organization>
</rdf:RDF>
				
			

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<String> subject, 
                            Optional<String> predicate, 
                            Optional<String> object, 
                            Optional<String> graph, 
                            Optional<Integer> 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:

				
					<http://acme.com/people/KenSmith> <foaf:name> "Ken Smith" .
<http://acme.com/people/DoraHug> <foaf:name> "Dora Hug" .
<http://acme.com/people/LyuKey> <foaf:name> "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-00001> : 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: <https://spaziocodice.com/customers/>

SELECT ?p ?o
WHERE 
{
  customers:1  ?p ?o  . 
}
				
			
Example #3: Give me the customers (URI) and their role
				
					PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX org: <http://www.w3.org/ns/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: <http://xmlns.com/foaf/0.1/>

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.

Share this post

Leave a Reply

Discover more from SpazioCodice

Subscribe now to keep reading and get access to the full archive.

Continue reading