EOSC Node DCAT Service Catalogue Implementation Guide

Following on from the #EOSC hackathon I ran a few weeks ago, I thought I would write a brief implementation guide for any other nodes that want to try playing with what we did

Marcus Povey

Following on from an earlier post around the hackathon I ran, where we took a couple of EOSC node service catalogues and federated them together, I have been repeatedly asked if I’d go into a little more detail as to what we did. My hope is that other nodes might want to start playing with this too, and letting me know where some of the gaps are, and hopefully this might result in a bit of a bottom up federation starting to form!

The Scope

In the hackathon we took the existing EOSC EU Node (EEN) service catalogue format, which some nodes already expose and mapped it over DCAT + JSON-LD using a schema mapping I put together below.

The choice of DCAT came out of the semantic interoperability work, and is well understood and extensible. The EOSC node service catalogue format, which was an output from EOSC Future, is a little bit more custom and less extensible in its current form. With that in mind I only mapped the minimal set of required fields associated with service discovery, and such mappings should not be considered canonical – this is very much a proof of concept.

Metadata for more advanced functionality (search, order provisioning, etc) is considered out of scope, at least for now.

Mapping EEN to DCAT

Our respective nodes in the hackathon already exposed their services via a public endpoint in EEN format (well, the Life Sciences Connect node, actually exposed it in ARIA format, but I had already done some work to map that to EEN via my micro service), so the next step was to map this across to DCAT.

This is the mapping table I came up with:

EEN field Required DCAT-compatible mapping Notes 
serviceBundle.id / service.id Yes dcterms:identifier and resource URI Use as stable ID. If not URI, mint one. 
name Yes dcterms:title Main display title. 
webpage Yes dcat:landingPage Human-facing service page. 
description Yes dcterms:description Main abstract. 
scientificDomains[].scientificDomain Yes dcat:theme → skos:Concept Use EEN scientific domain concept scheme. 
categories[].category Yes dcterms:type or dcat:theme → skos:Concept Suggesteddcterms:type for service type, optionally also dcat:theme. 
targetUsers[] Yes dcterms:audience → skos:Concept Not DCAT-native, but DC Terms is compatible. 
languageAvailabilities[] Yes dcterms:language Use ISO 639-1/BCP47 values, preferably lowercase like en, nl. 
trl Yes eosc:technologyReadinessLevel → skos:Concept Needs a small EOSC extension property. 
orderType Yes eosc:orderType or dcterms:accessRights→ skos:Concept open_access can also map to access rights. 
accessModes[] No dcterms:accessRights→ skos:Concept Good fit for free/conditional/restricted concepts. 
alternativeIdentifiers[] No adms:identifier or repeated dcterms:identifier Useadms:Identifier if you need type/value. 
tagline No dcterms:abstract or schema:slogan I’d useschema:slogan if using schema.org. 
tags[] No dcat:keyword Plain literals. 
helpdeskEmail No dcat:contactPoint / vcard:hasEmail Contact point object. 
termsOfUse, privacyPolicy, accessPolicy No dcterms:rights, dcterms:accessRights, odrl:hasPolicy, or foaf:page Depends how formal you want policies to be. 

In a case of comforting parallel evolution, another node produced a very similar mapping, so I was at least on the right track.

I made a fairly opinionated decision to use JSON-LD here, and as far as controlled vocabularies are concerned I was a little bit hand wavy. I also had to handle some data inconsistencies, for example, some fields being arrays even when only containing one item. Rather than argue who was right, I just handled things gracefully. Finally, I did not attempt to handle pagination in the first instance either, not that anybody has a lot of services right now.

For those of you who already expose an EEN feed, you might find my little micro service handy. Pull requests welcome!

Some additional plumbing…

One of the least specified aspect about all of these feeds, speaking as someone who came from the world of web standards and hacking on social networking applications, was that there was no plumbing around these that I could find. We had feeds, yes, but there was no apparent discovery mechanism.

I had poked around and there was something to do with “service capability discovery” that came out of the EOSC Beyond project. I have a sample below, and I would love to link you a specification, but I have literally only seen a JSON blob!

{ 
    "node_endpoint": "https://pilot-node.instruct-eric.org/api/capabilities", 
    "capabilities": [ 
        { 
            "capability_type": "Resource Catalogue", 
            "endpoint": "https://pilot-node.instruct-eric.org/catalogue/services", 
            "version": "1.0.0", 
            "api_spec": null, 
            "protocol": "REST", 
            "status": "OPERATIONAL" 
        }, 
        { 
            "capability_type": "Monitoring", 
            "endpoint": "https://status.api.aria.services", 
            "version": "1.0.0", 
            "api_spec": null, 
            "protocol": null, 
            "status": null 
        }, 
        { 
            "capability_type": "Helpdesk", 
            "endpoint": "https://instruct-helpdesk.scc.kit.edu", 
            "version": "1.0.0", 
            "api_spec": null, 
            "protocol": null, 
            "status": null 
        }, 
        { 
            "capability_type": "AAI", 
            "endpoint": "https://auth.aria.services/auth/realms/ARIA", 
            "version": "1.0.0", 
            "api_spec": null, 
            "protocol": null, 
            "status": null 
        }, 
        { 
            "capability_type": "Front Office", 
            "endpoint": "https://instruct-eric.org", 
            "version": "1.0.0", 
            "api_spec": null, 
            "protocol": null, 
            "status": null 
        } 
    ] 
} 

A JSON blob on it’s own is no use, really, so I made an opinionated decision to stick it at .well-known/eosc-federation/node which worked quite well, although with my “internet” hat on I would also probably want to link to it from a <link> header or something – e.g <link rel="eosc-federation-node" href="...">.

I wrote a discovery library which finds these capabilities that you might find helpful, again pull requests welcome.

Conclusion

As I discussed in my hackathon debrief, this leaves a lot of things unaddressed – search, pagination, service identity and disambiguation, amongst others.

I should also stress that this is in no way “official”, it’s just me and some folks poking around and seeing what we can build. That being said, feel free to use what has been do here for your node as well, and let me have any feedback you may have!

Leave a Reply