I don't understand how that config is getting parsed at all. It's not valid 
Turtle.

> ja:loadClass "io.bdrc.ldsearch.query.functions.CustomARQFunctions" .

is not a triple at all. It should probably be:

[] ja:loadClass "io.bdrc.ldsearch.query.functions.CustomARQFunctions" .

Riot gives "Expected IRI for predicate: got: 
[STRING:io.bdrc.ldsearch.query.functions.CustomARQFunctions]"

It's not clear to me how you could be successfully loading your extension 
function with invalid config.

Adam Soroka


> On Dec 26, 2017, at 1:42 PM, Marc Agate <[email protected]> wrote:
> 
> Well...
> 
> Here is the query
> 
> PREFIX : <http://purl.bdrc.io/ontology/core/>  
> PREFIX adm: <http://purl.bdrc.io/ontology/admin/>  
> PREFIX bdr: <http://purl.bdrc.io/resource/>  
> PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> 
> PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
> PREFIX skos: <http://www.w3.org/2004/02/skos/core#>  
> PREFIX tbr: <http://purl.bdrc.io/ontology/toberemoved/> 
> PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> 
> PREFIX f: <java:io.bdrc.ldsearch.query.functions.CustomARQFunctions.>
> 
> SELECT DISTINCT ?l 
> WHERE { 
> ?x skos:prefLabel ?l .  
> FILTER (f:myFilter(?l) < 100) 
> }
> 
> Note that whene I change FILTER (f:myFilter(?l) < 100)  to FILTER
> (STRLEN(?l) < 100), I don't get the 404 exception...
> Therefore it's not a connection issue. I thing it's more like a
> unresolved URI or so.
> 
> Now, since you'are asking for it, here is the full fuseki config:
> 
> ################################################################
> # Fuseki configuration for BDRC, configures two endpoints:
> #   - /bdrc is read-only
> #   - /bdrcrw is read-write
> #
> # This was painful to come up with but the web interface basically
> allows no option
> # and there is no subclass inference by default so such a configuration
> file is necessary.
> #
> # The main doc sources are:
> #  - https://jena.apache.org/documentation/fuseki2/fuseki-configuration
> .html
> #  - https://jena.apache.org/documentation/assembler/assembler-howto.ht
> ml
> #  - https://jena.apache.org/documentation/assembler/assembler.ttl
> #
> # See https://jena.apache.org/documentation/fuseki2/fuseki-layout.html
> for the destination of this file.
> 
> @prefix fuseki:  <http://jena.apache.org/fuseki#> .
> @prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
> @prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#> .
> @prefix tdb:     <http://jena.hpl.hp.com/2008/tdb#> .
> # @prefix tdb2:    <http://jena.apache.org/2016/tdb#> .
> @prefix ja:      <http://jena.hpl.hp.com/2005/11/Assembler#> .
> @prefix :        <http://base/#> .
> @prefix text:    <http://jena.apache.org/text#> .
> @prefix skos:    <http://www.w3.org/2004/02/skos/core#> .
> @prefix adm:     <http://purl.bdrc.io/ontology/admin/> .
> @prefix bdd:     <http://purl.bdrc.io/data/> .
> @prefix bdo:     <http://purl.bdrc.io/ontology/core/> .
> @prefix bdr:     <http://purl.bdrc.io/resource/> .
> @prefix f: <java:io.bdrc.ldsearch.query.functions.CustomARQFunctions.>
> .
> 
> ja:loadClass "io.bdrc.ldsearch.query.functions.CustomARQFunctions" .
> # [] ja:loadClass "org.seaborne.tdb2.TDB2" .
> # tdb2:DatasetTDB2  rdfs:subClassOf  ja:RDFDataset .
> # tdb2:GraphTDB2    rdfs:subClassOf  ja:Model .
> 
> [] rdf:type fuseki:Server ;
>    fuseki:services (
>      :bdrcrw
> #      :bdrcro
>    ) .
> 
> :bdrcrw rdf:type fuseki:Service ;
>     fuseki:name                       "bdrcrw" ;     # name of the
> dataset in the url
>     fuseki:serviceQuery               "query" ;    # SPARQL query
> service
>     fuseki:serviceUpdate              "update" ;   # SPARQL update
> service
>     fuseki:serviceUpload              "upload" ;   # Non-SPARQL upload
> service
>     fuseki:serviceReadWriteGraphStore "data" ;     # SPARQL Graph store
> protocol (read and write)
>     fuseki:dataset                    :bdrc_text_dataset ;
>     .
> 
> # :bdrcro rdf:type fuseki:Service ;
> #     fuseki:name                     "bdrc" ;
> #     fuseki:serviceQuery             "query" ;
> #     fuseki:serviceReadGraphStore    "data" ;
> #     fuseki:dataset                          :bdrc_text_dataset ;
> #     .
> 
> # using TDB
> :dataset_bdrc rdf:type      tdb:DatasetTDB ;
>      tdb:location "/etc/fuseki/databases/bdrc" ;
>      tdb:unionDefaultGraph true ;
>      .
> 
> # # try using TDB2
> # :dataset_bdrc rdf:type      tdb2:DatasetTDB2 ;
> #      tdb2:location "/etc/fuseki/databases/bdrc" ;
> #      tdb2:unionDefaultGraph true ;
> #   .
> 
> :bdrc_text_dataset rdf:type     text:TextDataset ;
>     text:dataset   :dataset_bdrc ;
>     text:index     :bdrc_lucene_index ;
>     .
> 
> # Text index description
> :bdrc_lucene_index a text:TextIndexLucene ;
>     text:directory <file:/etc/fuseki/lucene-bdrc> ;
>     text:storeValues true ;
>     text:multilingualSupport true ;
>     text:entityMap :bdrc_entmap ;
>     text:defineAnalyzers (
>         [ text:addLang "bo" ; 
>           text:analyzer [ 
>             a text:GenericAnalyzer ;
>             text:class "io.bdrc.lucene.bo.TibetanAnalyzer" ;
>             text:params (
>                 [ text:paramName "segmentInWords" ;
>                   text:paramType text:TypeBoolean ; 
>                   text:paramValue false ]
>                 [ text:paramName "lemmatize" ;
>                   text:paramType text:TypeBoolean ;
>                   text:paramValue true ]
>                 [ text:paramName "filterChars" ;
>                   text:paramType text:TypeBoolean ;
>                   text:paramValue false ]
>                 [ text:paramName "fromEwts" ;
>                   text:paramType text:TypeBoolean ;
>                   text:paramValue false ]
>                 )
>             ] ; 
>           ]
>         [ text:addLang "bo-x-ewts" ; 
>           text:analyzer [ 
>             a text:GenericAnalyzer ;
>             text:class "io.bdrc.lucene.bo.TibetanAnalyzer" ;
>             text:params (
>                 [ text:paramName "segmentInWords" ;
>                   text:paramType text:TypeBoolean ; 
>                   text:paramValue false ]
>                 [ text:paramName "lemmatize" ;
>                   text:paramType text:TypeBoolean ;
>                   text:paramValue true ]
>                 [ text:paramName "filterChars" ;
>                   text:paramType text:TypeBoolean ;
>                   text:paramValue false ]
>                 [ text:paramName "fromEwts" ;
>                   text:paramType text:TypeBoolean ;
>                   text:paramValue true ]
>                 )
>             ] ; 
>           ]
>       ) ;
>     .
> 
> # Index mappings
> :bdrc_entmap a text:EntityMap ;
>     text:entityField      "uri" ;
>     text:uidField         "uid" ;
>     text:defaultField     "label" ;
>     text:langField        "lang" ;
>     text:graphField       "graph" ; ## enable graph-specific indexing
>     text:map (
>          [ text:field "label" ; 
>            text:predicate skos:prefLabel ]
>          [ text:field "altLabel" ; 
>            text:predicate skos:altLabel ; ]
>          [ text:field "rdfsLabel" ;
>            text:predicate rdfs:label ; ]
>          [ text:field "chunkContents" ;
>            text:predicate bdo:chunkContents ; ]
>          [ text:field "eTextTitle" ;
>            text:predicate bdo:eTextTitle ; ]
>          [ text:field "logMessage" ;
>            text:predicate adm:logMessage ; ]
>          [ text:field "noteText" ;
>            text:predicate bdo:noteText ; ]
>          [ text:field "workAuthorshipStatement" ;
>            text:predicate bdo:workAuthorshipStatement ; ]
>          [ text:field "workColophon" ; 
>            text:predicate bdo:workColophon ; ]
>          [ text:field "workEditionStatement" ;
>            text:predicate bdo:workEditionStatement ; ]
>          [ text:field "workPublisherLocation" ;
>            text:predicate bdo:workPublisherLocation ; ]
>          [ text:field "workPublisherName" ;
>            text:predicate bdo:workPublisherName ; ]
>          [ text:field "workSeriesName" ;
>            text:predicate bdo:workSeriesName ; ]
>          ) ;
>     .
> ###################################################################
> 
> It would be wonderful to have the java:URI scheme thing working (all
> custom functions in a single class and method calls done directly in
> the sparql query : sounds like a dream !)
> 
> Marc
> 
> Le mardi 26 décembre 2017 à 13:22 -0500, ajs6f a écrit :
>> That exception doesn't appear to have anything to do with extension
>> functions. It indicates a problem between client and server.
>> 
>> Please show at _least_ your actual query execution code, your
>> complete Fuseki config, and a complete stacktrace.
>> 
>> 
>> ajs6f
>> 
>>> On Dec 26, 2017, at 1:17 PM, Marc Agate <[email protected]>
>>> wrote:
>>> 
>>> I forgot to mention that according to 
>>> https://jena.apache.org/documentation/query/java-uri.html
>>> I tried for testing purpose to set a PREFIX f:
>>> <java:io.bdrc.ldsearch.query.functions.CustomARQFunctions.>and
>>> added
>>> the following to fuseki config : 
>>> ja:loadClass "io.bdrc.ldsearch.query.functions.CustomARQFunctions"
>>> .
>>> where CustomARQFunctions is :
>>> public class CustomARQFunctions {           public static
>>> NodeValue myFilter(NodeValue value1){                       int i
>>> =
>>> value1.asString().length();         return
>>> NodeValue.makeInteger(i);     }
>>> }
>>> since according to 
>>> https://jena.apache.org/documentation/query/writing_functions.html
>>> using the java:URI scheme "dynamically loads the code, which must
>>> be on
>>> the Java classpath. With this scheme, the function URI gives the
>>> class
>>> name. There is automatic registration of a wrapper into the
>>> function
>>> registry. This way, no explicit registration step is needed by the
>>> application and queries issues with the command line tools can load
>>> custom functions."
>>> but no luck: I keep getting the following exception:
>>> Exception in thread "main" HttpException: 404       at
>>> org.apache.jena.sparql.engine.http.HttpQuery.execGet(HttpQuery.java
>>> :328
>>> )   at
>>> org.apache.jena.sparql.engine.http.HttpQuery.exec(HttpQuery.java:28
>>> 8)  
>>> at
>>> org.apache.jena.sparql.engine.http.QueryEngineHTTP.execResultSetInn
>>> er(Q
>>> ueryEngineHTTP.java:348)    at
>>> org.apache.jena.sparql.engine.http.QueryEngineHTTP.execSelect(Query
>>> Engi
>>> neHTTP.java:340)
>>> I am stuck !
>>> Marc
>>> Le mardi 26 décembre 2017 à 18:56 +0100, Marc Agate a écrit :
>>>> Hi,
>>>> Adam's gave me the right direction.
>>>> I managed to load my function class in fuseki config using
>>>> ja:loadClass
>>>> but now remains the following issue (the function is not
>>>> registered)seefuseki logs :
>>>> [2017-12-26 16:10:13] exec       WARN  URI <http://purl.bdrc.io/f
>>>> unct
>>>> ions#MyFilterFunction> has no registered function factory
>>>> How can I register this function now that I have the code
>>>> available
>>>> onthe endpoint side ?
>>>> Thanks for helping
>>>> Marc.
>>>> 
>>>> Le mardi 26 décembre 2017 à 17:43 +0000, Andy Seaborne a écrit :
>>>>> As well s Adam's point (and all the libraries your function
>>>>> needs, transitively)
>>>>> What is in the Fuseki log file?How was the data loaded into
>>>>> Fuseki?
>>>>>  >> I printed out the >> FunctionRegistry
>>>>>      And
>>>>> On 26/12/17 14:51, ajs6f wrote:
>>>>>> I'm not as familiar with the extension points of ARQ as I
>>>>>> wouldlike to be, but as I understand what you are doing, you
>>>>>> areregistering a new function with your _local_ registry,
>>>>>> then
>>>>>> firinga query at a _remote_ endpoint (which has a completely
>>>>>> independentregistry in a different JVM in a different
>>>>>> process,
>>>>>> potentially ina different _system_).
>>>>>> The query is getting interpreted and executed by that
>>>>>> remoteservice, not locally. So you need to register the
>>>>>> function
>>>>>> _there_.
>>>>>> Take a look at this thread:
>>>>>> https://lists.apache.org/thread.html/1cda23332af4264883e88697
>>>>>> d994
>>>>>> 605770edcde2f93ddea51240e4b8@%3Cusers.jena.apache.org%3E
>>>>>> It should get you started as to how to register
>>>>>> extensionfunctionality in Fuseki.
>>>>>> 
>>>>>> Adam Soroka
>>>>>>> On Dec 26, 2017, at 9:34 AM, Marc Agate <[email protected]
>>>>>>> om>
>>>>>>> wrote:
>>>>>>> 
>>>>>>> Hi !
>>>>>>> 
>>>>>>> I successfully implemented sparql queries using custom ARQ
>>>>>>> functions
>>>>>>> using the following (custom function code):
>>>>>>> 
>>>>>>> ****************
>>>>>>> public class LevenshteinFilter extends FunctionBase2 {
>>>>>>> 
>>>>>>>      public LevenshteinFilter() { super() ; }
>>>>>>> 
>>>>>>>      public NodeValue exec(NodeValue value1, NodeValue
>>>>>>> value2){
>>>>>>>          LevenshteinDistance LD=new LevenshteinDistance();
>>>>>>>          int i = LD.apply(value1.asString(),
>>>>>>> value2.asString());
>>>>>>>          return NodeValue.makeInteger(i);
>>>>>>>      }
>>>>>>> }
>>>>>>> ***************
>>>>>>> 
>>>>>>> it works fine when I query against a Model loaded from a
>>>>>>> turtle
>>>>>>> file,
>>>>>>> like this:
>>>>>>> 
>>>>>>> ***************
>>>>>>> InputStream input =
>>>>>>> QueryProcessor.class.getClassLoader().getResourceAsStream("
>>>>>>> full
>>>>>>> .t
>>>>>>> tl");
>>>>>>>              model =
>>>>>>> ModelFactory.createMemModelMaker().createModel("default");
>>>>>>>              model.read(input,null,"TURTLE"); // null base
>>>>>>> URI,
>>>>>>> since
>>>>>>> model URIs are absolute
>>>>>>>              input.close();
>>>>>>> ***************
>>>>>>> 
>>>>>>> with the query being sent like this :
>>>>>>> 
>>>>>>> ***************
>>>>>>> String functionUri = "http://www.example1.org/LevenshteinFu
>>>>>>> ncti
>>>>>>> on
>>>>>>> ";
>>>>>>>          FunctionRegistry.get().put(functionUri ,
>>>>>>> LevenshteinFilter.class);
>>>>>>> 
>>>>>>>          String s = "whatever you want";
>>>>>>>          String sparql = prefixes+" SELECT DISTINCT ?l
>>>>>>> WHERE {
>>>>>>> ?x
>>>>>>> rdfs:label ?l . " +  "FILTER(fct:LevenshteinFunction(?l,
>>>>>>> \"" +
>>>>>>> s
>>>>>>> + "\")
>>>>>>> < 4) }";
>>>>>>>          Query query = QueryFactory.create(sparql);
>>>>>>>          QueryExecution qexec =
>>>>>>> QueryExecutionFactory.create(query,
>>>>>>> model);
>>>>>>>          ResultSet rs = qexec.execSelect();
>>>>>>> ***************
>>>>>>> 
>>>>>>> However, if i use a working fuseki endpoint for the same
>>>>>>> dataset
>>>>>>> (full.ttl) like this :
>>>>>>> 
>>>>>>> ***************
>>>>>>> fusekiUrl="http://localhost:3030/ds/query";;
>>>>>>> ***************
>>>>>>> 
>>>>>>> sending the query like this (using
>>>>>>> QueryExecutionFactory.sparqlService(fusekiUrl,query)
>>>>>>> instead of
>>>>>>> QueryExecutionFactory.create(query,model) ):
>>>>>>> 
>>>>>>> ***************
>>>>>>> String functionUri = "http://www.example1.org/LevenshteinFu
>>>>>>> ncti
>>>>>>> on
>>>>>>> ";
>>>>>>>          FunctionRegistry.get().put(functionUri ,
>>>>>>> LevenshteinFilter.class);
>>>>>>> 
>>>>>>>          String s = "whatever you want";
>>>>>>>          String sparql = prefixes+" SELECT DISTINCT ?l
>>>>>>> WHERE {
>>>>>>> ?x
>>>>>>> rdfs:label ?l . " + "FILTER(fct:LevenshteinFunction(?l, \""
>>>>>>> + s
>>>>>>> +
>>>>>>> "\")
>>>>>>> < 4) }";
>>>>>>>          Query query = QueryFactory.create(sparql);
>>>>>>>          QueryExecution qexec =
>>>>>>> QueryExecutionFactory.sparqlService(fusekiUrl,query);
>>>>>>>          ResultSet rs = qexec.execSelect();
>>>>>>> ***************
>>>>>>> 
>>>>>>> Then I don't get any results back. In both cases I printed
>>>>>>> out
>>>>>>> the
>>>>>>> FunctionRegistry and they contain exactly the same entries,
>>>>>>> especially
>>>>>>> :
>>>>>>> 
>>>>>>> key=http://www.example1.org/LevenshteinFunction value:
>>>>>>> org.apache.jena.sparql.function.FunctionFactoryAuto@5a45133
>>>>>>> e
>>>>>>> 
>>>>>>> Any clue ?
>>>>>>> 
>>>>>>> Thanks
>> 
>> 

Reply via email to