Search code examples
javardfsparqljenalinkedmdb

Get URI from resource in ResultSet


I am trying to get the URI from the a resource in Java, but it is always null. Right now, I am trying this:

for ( ; rs.hasNext() ; ) {
  QuerySolution qs  = rs.next();
  System.out.println( qs.getLiteral("label"));
  System.out.println( qs.getResource("label"));
  …

The literal is returned just fine, I even tried the resource "?film", but still resource is null. Here is my SPARQL query:

PREFIX mdb: <http://data.linkedmdb.org/resource/movie/film>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
select ?label ?film where {
  ?film mdb:id ?uri .
  ?film rdfs:label ?label . 
  filter regex(?label,  + queryVar +
}

queryVar is just the user input, for example "Batman".

Edit:I had an typo in my query: this was my query:

String sparqlQuery = "PREFIX mdb: http://data.linkedmdb.org/resource/movie/film" + "PREFIX rdfs: http://www.w3.org/2000/01/rdf-schema# " + "select ?label ?film" + "where " + "{ ?film mdb:id ?uri ." + "?film rdfs:label ?label . " + " }" + "";

See closely at ?film and where, they become filmwhere, thats the problem.

Thanks to Joshua I figured it out.


Solution

  • The documentation for QuerySolution#getResource says

    Resource getResource(String varName)

    Return the value of the named variable in this binding, casting to a Resource. A return of null indicates that the variable is not present in this solution. An exception indicates it was present but not a resource.

    If you're getting null, then some value isn't present in the query solution. However, without seeing your actual query, it's impossible to tell whether you're getting empty results for some reason (e.g., the queryVar isn't what you think it is), or not. If queryVar is just a String without surrounding quotes, you'd end up with a query like

    filter regex(?label,Batman)
    

    instead of

    filter regex(?label,"Batman")
    

    At any rate, I modified your query to be one that we can run with Jena's command line tools:

    PREFIX mdb: <http://data.linkedmdb.org/resource/movie/film>
    PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> 
    select ?label ?film
    where {
      service <http://data.linkedmdb.org/sparql> {
        ?film mdb:id ?uri .
        ?film rdfs:label ?label . 
        filter regex(?label, "Batman")
      }
    }
    

    When I run this, I get results like:

    $ arq --query query.sparql --data data.n3 
    -----------------------------------------------------------------------------------------
    | label                                | film                                           |
    =========================================================================================
    | "Batman"                             | <http://data.linkedmdb.org/resource/film/2>    |
    | "Batman"                             | <http://data.linkedmdb.org/resource/film/3>    |
    | "Batman & Robin"                     | <http://data.linkedmdb.org/resource/film/4>    |
    | "Batman: Mask of the Phantasm"       | <http://data.linkedmdb.org/resource/film/737>  |
    | "Batman: Mystery of the Batwoman"    | <http://data.linkedmdb.org/resource/film/974>  |
    | "Batman Beyond: Return of the Joker" | <http://data.linkedmdb.org/resource/film/1802> |
    | "Batman & Mr. Freeze: SubZero"       | <http://data.linkedmdb.org/resource/film/2124> |
    -----------------------------------------------------------------------------------------
    

    in which label and film are always bound. All of the labels are literals, so you should be able to do

    qs.getLiteral("label")
    

    and get a literal. It sounds more like you want the URI of the film variable, which you would do with

    qs.getResource("film").getURI()
    

    You could, of course, use toString() afterward if you want the URI string.

    As an aside, rather than doing

    "filter(?label, " + queryVar + "…"
    

    you might want to consider using a ParameterizedSparqlString to safely substitute the queryVar in. Otherwise, what happens with queryVar is something like

    "\"Batman\") UNION { ?film hasPassword ?label }"
    

    and it gets substituted in? You suddenly leak a bunch of information. Even if nothing sensitive gets out, you could still end up causing a big load on the SPARQL endpoint, effectively launching a denial-of-service attack.