You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2022/05/31 08:53:56 UTC

[jena-site] branch main updated: Initial documentation for custom service executors

This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena-site.git


The following commit(s) were added to refs/heads/main by this push:
     new a2e0a3c4e Initial documentation for custom service executors
a2e0a3c4e is described below

commit a2e0a3c4e0d7e8f503a1119efaa7053a81248c8e
Author: Claus Stadler <Ra...@googlemail.com>
AuthorDate: Thu Apr 28 19:42:56 2022 +0200

    Initial documentation for custom service executors
---
 .../query/custom_service_executors.md              | 72 ++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/source/documentation/query/custom_service_executors.md b/source/documentation/query/custom_service_executors.md
new file mode 100644
index 000000000..f7693eb2d
--- /dev/null
+++ b/source/documentation/query/custom_service_executors.md
@@ -0,0 +1,72 @@
+---
+title: ARQ - Custom Service Executors
+---
+
+Since Jena 4.2.0 ARQ features a plugin system for custom service executors.
+The relevant classes are located in the package `org.apache.jena.sparql.service` and are summarized as follows:
+
+* `ServiceExecutorRegistry`: A registry that holds a list of service executors. When Jena starts up, it configures a default registry to handle `SERVICE` requests against HTTP SPARQL endpoints and registers it with the global ARQ context accessible under `ARQ.getContext()`.
+
+* `ServiceExecutorFactory`: This is the main interface for custom SERVICE handler implementations:
+```java
+public interface ServiceExecutorFactory {
+    public ServiceExecution createExecutor(OpService substituted, OpService original, Binding binding, ExecutionContext execCxt);
+}
+```
+The second OpService parameter represents the original `SERVICE` clause as it occurs in the query, whereas the first parameter is the OpService obtained after substitution of all mentioned variables w.r.t. the current binding.
+A `ServiceExecutorFactory` can indicate its non-applicability for handling a request simply by returning `null`. In that case, Jena will ask the next service executor factory in the registry. If a request remains unhandled then the QueryExecException `No SERVICE handler` is raised.
+
+
+* `ServiceExecution`: If a `ServiceExectorFactory` can handle a request then it needs to returns a `ServiceExecution` instance:
+```java
+public interface ServiceExecution {
+    public QueryIterator exec();
+}
+```
+The actual execution is started by calling the `exec()` method which returns a `QueryIterator`.
+Note, that there are uses cases where ServiceExecution instances may not have to be executed. For example, one may analyze which service executor factories among a set of them claim to be capable of handling a request. This can be useful for debugging or display in a dashboard of applicable service executors.
+
+## Examples
+A runnable example suite is located in the jena-examples module at [CustomServiceExecutor.java](https://github.com/apache/jena/blob/main/jena-examples/src/main/java/arq/examples/service/CustomServiceExecutor.java).
+
+In the remainder we summarize the essentials of setting up a custom service executor.
+The following snippet sets up a simple service executor factory that relays queries targeted at Wikidata to DBpedia:
+
+```java
+Node WIKIDATA = NodeFactory.createURI("http://query.wikidata.org/sparql");
+Node DBPEDIA = NodeFactory.createURI("http://dbpedia.org/sparql");
+
+ServiceExecutorFactory myExecutorFactory = (opExecute, original, binding, execCxt) -> {
+    if (opExecute.getService().equals(WIKIDATA)) {
+        opExecute = new OpService(DBPEDIA, opExecute.getSubOp(), opExecute.getSilent());
+        return ServiceExecutorRegistry.httpService.createExecutor(opExecute, original, binding, execCxt);
+    }
+    return null;
+};
+```
+
+### Global vs Local Service Executor Registration
+The global registry can be accessed and modified as shown below:
+```java
+ServiceExecutorRegistry globalRegistry = ServiceExecutorRegistry.get();
+
+// Note: registry.add() prepends executor factories to the internal list such
+// that they are consulted first!
+globalRegistry.add(myExecutorFactory);
+
+```
+
+The following snippet shows how a custom service executor can be configured locally for an individual query execution:
+```java
+Context cxt = ARQ.getContext().copy();
+ServiceExecutorRegistry localRegistry = ServiceExecutorRegistry().get().copy();
+localRegistry.add(myExecutorFactory);
+
+String queryStr = "SELECT * { SERVICE <http://query.wikidata.org/sparql> { ?s ?p "Apache Jena"@en } }";
+try (QueryExecution qe = QueryExecutionFactory.create(queryStr)) {
+  ServiceExecutorRegistry.set(qe.getContext(), registry);
+  // ...
+}
+
+```
+