Skip to content
This repository has been archived by the owner on Sep 11, 2023. It is now read-only.

Latest commit

 

History

History

remoting

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Tractus-X Remoting Agent (KA-RMT)

KA-RMT is a module of the Tractus-X Knowledge Agents Reference Implementations.

  • see copyright notice in the top folder
  • see license file in the top folder
  • see authors file in the top folder

About this Module

This is a folder providing a FOSS implementations of a Function Binding (aka Remoting) Agent.

Binding Agents are needed by any Agent-Enabled dataspace providers to connect the dataspace protocol/representation (here: a combination of the SPARQL query language/operating on RDF triple graphs) to the underlying business data and logic.

The Remoting Agent in particular is able to interact with typical REST backend services based on XML and/or JSON payloads. The SPARQL profile which is used is called KA-BIND-F (the Knowledge Agent Functional Binding Profile).

Architecture

Tractus-X Remoting Agent is built on Eclipse RDF4J by introducing a (virtual) storage and inference layer (SAIL) that is indeed is backed by local Java classes and/or remote REST services.

Remoting Agent Architecture

The Remoting SAIL provides the implementation of a so-called repository (=a SPARQL endpoint that can be used as the target address of an EDC asset and/or as a service context in federated queries).

Each remoting repository is configured in a TTL (Terse Triple Language) configuration file using the org.eclipse.tractusx.agents:Remoting Sailtype and lists the available functions (=a particular class of nodes). Each remoting repository is parsed, represented and possibly exported from the runtime by means of Remoting SAIL Config, for each function (class), a corresponding Service Config is maintained.

Here is an example repository configuration which uses the public service https://api.agify.io to make a prediction of the age of a person given its name.

# ... PREFIX declarations

[] rdf:type rep:Repository ;
   rep:repositoryID "prognosis" ;
   rdfs:label "Prognosis Functions" ;
   rep:repositoryImpl [
      rep:repositoryType "openrdf:SailRepository" ;
      sr:sailImpl [
         sail:sailType "org.eclipse.tractusx.agents:Remoting" ;
         cx-fx:callbackAddress <http://localhost:8888/callback>;
         cx-fx:supportsInvocation prognosis:Prognosis;
      ]
   ].

# Function declaration

prognosis:Prognosis rdf:type cx-fx:Function;
  dcterms:description "Prognosis is a sample simulation function with input and output bindings."@en ;
  dcterms:title "Prognosis" ;
  cx-fx:targetUri "https://api.agify.io";
  cx-common:authenticationCode "Dummy-Authorization";
  cx-common:authenticationKey "Dummy-Key";
  cx-fx:input prognosis:name;
  cx-fx:result prognosis:hasResult.

prognosis:name rdf:type cx-fx:Argument;
  dcterms:description "Name is an argument to the Prognosis function."@en ;
  dcterms:title "Name";
  cx-fx:argumentName "name".

prognosis:hasResult rdf:type cx-fx:Result;
  cx-fx:output prognosis:prediction;
  cx-fx:output prognosis:support.

prognosis:prediction rdf:type cx-fx:ReturnValue;
   dcterms:description "Prediction (Value) is an integer-based output of the Prognosis function."@en ;
   dcterms:title "Prediction" ;
   cx-fx:valuePath "age";
   cx-fx:dataType xsd:int.

prognosis:support rdf:type cx-fx:ReturnValue;
   dcterms:description "Support (Value) is another integer-based output of the Prognosis function."@en ;
   dcterms:title "Support" ;
   cx-fx:valuePath "count";
   cx-fx:dataType xsd:int.

# Further declarations ...

When a concrete query is sent to the RDF4J controller, a Remoting SAIL Connection is setup which evaluates the query with the help of the stateful Query Executor. With the help of the Remoting Sail Configuraiton, The Query Executor instantiates all function nodes as Invocations. During processing, input and output variables are accessed and stored in a BindingSet Collection for which the Query Executor implements the IBindingHost.

PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> 
PREFIX prognosis: <https://w3id.org/catenax/ontology/prognosis#> 

SELECT ?name ?invocation ?prediction ?support 
WHERE { 
  VALUES (?name) { "Schorsch"^^xsd:string }
  ?invocation a prognosis:Prognosis; 
                prognosis:name ?name; 
                prognosis:prediction ?prediction;
                prognosis:support ?support.
}

Currently, there are two principle methods of function bindings available

  • Class Binding (Service Config.targetUri follows the pattern "class:#")
  • REST Binding (Service ConfigtargetUri follows the pattern "https?://")

For REST Binding, we support the following outgoing request formats/content types (being configured via Service Config.method). Note that responses are always interpreted as XML or JSON depending on the response content type.

  • GET: Input arguments are mapped to URL query parameters.
  • POST-XML: Input Arguments are mapped into an XML document body with content-type "application/xml" T
  • POST-JSON: Input Arguments are mapped into an JSON document body with content-type "application/json"
  • POST-JSON-MF: Input Arguments are mapped into JSON-based files send in a multi-part request with content-type multipart/form-data (and XXX as boundary and "application/json" as Content-Disposition)
  • POST-XML-MF: Input Arguments are mapped into XML-based files send in a multi-part request with content-type multipart/form-data (and XXX as boundary and application/json as Content-Disposition)

Invocations can be batched. Normally (Service Config.batch is set to 1, no Argument Config.formsBatchGroup is set to true) Remoting Agent will produce an outgoing REST call for each incoming tuple/binding. If Service Config.batch is greater than 1 or there is some Argument Config.formsBatchGroup set to true, several tuples/bindings can be sent in a single invocation (usually in an array or by using flexible argument paths using '{}' path elements). In that case, we also expect the responses to contain several individual results which are mapped/joined with the original input bindings using the ResultConfig.correlationInput reference.

Invocation can be asynchronous. That means that the called backend will not return a proper response, just a successful notification code. Instead we send the public URL of the builtin CallbackController which is configured in the callbackAddress property of the remoting repository (and is transmitted in the callbackAddressProperty of the ServiceConfig). In order to correlate outgoing (batch) requests with asynchronous responses sent to the CallbackController, we rely on setting a unique request identifier specified in ServiceConfig.invocationIdProperty and comparing it with the content of the ResultConfig.callbackProperty

Deployment

Compile, Test & Package

mvn package

This will generate

  • a standalone jar containing all necessary rdf4j components to build your own repository server.
  • a pluging jar which maybe dropped into an rdf4j server for remoting support.

Run Locally

The standalone jar](target/remoting-agent-1.9.5-SNAPSHOT.jar) contains an example application that runs a sample repository against a sample source

java -jar target/remoting-agent-1.9.5-SNAPSHOT.jar -Dorg.slf4j.simpleLogger.defaultLogLevel=DEBUG

Containerizing

You could either call

mvn install -Pwith-docker-image

or invoke the following docker command after a successful package run

docker build -t ghcr.io/catenax-ng/product-agents/remoting-agent:1.9.5-SNAPSHOT -f src/main/docker/Dockerfile .

This will create a docker image including an extended rdf4j-server as well as an interactive rdf4j-workbench.

To run the docker image, you could invoke this command

docker run -p 8081:8081 \
  -v $(pwd)/src/test:/var/rdf4j/config \
  ghcr.io/catenax-ng/product-agents/remoting-agent:1.9.5-SNAPSHOT

Afterwards, you should be able to access the local SparQL endpoint via the browser or by directly invoking a query

curl --location --request POST 'http://localhost:8081/resources' \
--header 'Content-Type: application/sparql-query' \
--header 'Accept: application/json' \
--data-raw 'PREFIX : <http://example.org/voc#>

SELECT ?x
WHERE {
   ?x a :Professor .
}'

You may manipulate any of the following environment variables to configure the image behaviour. Note that there is no builtin security (ssl/auth) for the exposed endpoints. This must be provided by hiding them in an appropriate service network layer.

ENVIRONMENT VARIABLE Required Example Description List
JAVA_TOOL_OPTIONS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8090 JMV (Debugging option) X

Helm Chart

A helm chart for deploying the remoting agent can be found under this folder.

It can be added to your umbrella chart.yaml by the following snippet

dependencies:
  - name: remoting-agent
    repository: https://catenax-ng.github.io/product-knowledge/infrastructure
    version: 1.9.5-SNAPSHOT
    alias: my-remoting-agent

and then installed using

helm dependency update

In your values.yml, you configure your specific instance of the remoting agent like this

##############################################################################################
# API Binding Agent
##############################################################################################

my-remoting-agent: 
  securityContext: *securityContext
  nameOverride: my-remoting-agent
  fullnameOverride: my-remoting-agent
  ingresses:
    - enabled: true
      # -- The hostname to be used to precisely map incoming traffic onto the underlying network service
      hostname: "my-remoting-agent.public-ip"
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$1
        nginx.ingress.kubernetes.io/use-regex: "true"
      # -- Agent endpoints exposed by this ingress resource
      endpoints:
        - default
      tls:
        enabled: true
        secretName: my-remoting-tls
  repositories:
    prognosis: |-
      #
      # Rdf4j configuration for prognosis sample
      #
      @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
      @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
      @prefix rep: <http://www.openrdf.org/config/repository#>.
      @prefix sr: <http://www.openrdf.org/config/repository/sail#>.
      @prefix sail: <http://www.openrdf.org/config/sail#>.
      @prefix sp: <http://spinrdf.org/sp#>.
      @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
      @prefix json: <https://json-schema.org/draft/2020-12/schema#> .
      @prefix dcterms: <http://purl.org/dc/terms/> .
      @prefix cx-fx: <https://w3id.org/catenax/ontology/function#>.
      @prefix prognosis: <https://w3id.org/prognosis>.

    [] rdf:type rep:Repository ;
       rep:repositoryID "prognosis" ;
       rdfs:label "Prognosis Functions" ;
       rep:repositoryImpl [
          rep:repositoryType "openrdf:SailRepository" ;
          sr:sailImpl [
             sail:sailType "org.eclipse.tractusx.agents:Remoting" ;
             cx-fx:callbackAddress <https://my-remoting-agent.public-ip/callback>;
             cx-fx:supportsInvocation prognosis:Prognosis;
          ]
       ].
    
    # Function declaration
    
    prognosis:Prognosis rdf:type cx-fx:Function;
      dcterms:description "Prognosis is a sample simulation function with input and output bindings."@en ;
      dcterms:title "Prognosis" ;
      cx-fx:targetUri "https://api.agify.io";
      cx-common:authenticationCode "Dummy-Authorization";
      cx-common:authenticationKey "Dummy-Key";
      cx-fx:input prognosis:name;
      cx-fx:result prognosis:hasResult.
    
    prognosis:name rdf:type cx-fx:Argument;
      dcterms:description "Name is an argument to the Prognosis function."@en ;
      dcterms:title "Name";
      cx-fx:argumentName "name".
    
    prognosis:hasResult rdf:type cx-fx:Result;
      cx-fx:output prognosis:prediction;
      cx-fx:output prognosis:support.
    
    prognosis:prediction rdf:type cx-fx:ReturnValue;
       dcterms:description "Prediction (Value) is an integer-based output of the Prognosis function."@en ;
       dcterms:title "Prediction" ;
       cx-fx:valuePath "age";
       cx-fx:dataType xsd:int.
    
    prognosis:support rdf:type cx-fx:ReturnValue;
       dcterms:description "Support (Value) is another integer-based output of the Prognosis function."@en ;
       dcterms:title "Support" ;
       cx-fx:valuePath "count";
       cx-fx:dataType xsd:int.