content
| - %VOSWARNING%
%META:TOPICPARENT{name="VOSRDFDataProviders"}%
%VOSNAV%
---+ Virtuoso Sesame Provider
%TOC%
---++What is Sesame
Sesame is an open source Java framework for storing, querying, and reasoning with RDF and
RDF Schema. It can be used as a database for RDF and RDF Schema, or as a Java library for
applications that need to work with RDF internally. For example, suppose you need to read
a big RDF file, find the relevant information for your application, and use that information.
Sesame provides you with the necessary tools to parse, interpret, query, and store all this
information, embedded in your own application if you want, or, if you prefer, in a separate
database or even on a remote server. More generally: Sesame provides an application
developer with a toolbox that contains useful hammers, screwdrivers, etc., for 'Do-It-Yourself'
projects with RDF.
---++What is the Virtuoso Sesame Provider
The Virtuoso Sesame Provider is a fully operational Native Graph Model Storage Provider for
the Sesame Framework, allowing users of Virtuoso to leverage the Sesame framework to
modify, query, and reason with the Virtuoso quad store using the Java language. The Sesame
Repository API offers a central access point for connecting to the Virtuoso quad store. Its
purpose is to provides a Java-friendly access point to Virtuoso. It offers various methods for
querying and updating the data, while abstracting the details of the underlying machinery.
The Provider has been tested against the two latest currently available versions,
[[http://rdf4j.org/download.docbook?view][Sesame]] 2.6.x, 2.7.x, 2.8.x and the new Sesame 4.x release, for which a new Provider is available.
Fig. 1 Sesame Component Stack
%BR%%BR%%BR%%BR%
If you need more information about how to set up your environment for working with the
Sesame APIs, take a look at Chapter 2 of the Sesame User Guide,
[[http://rdf4j.org/sesame/2.7/docs/users.docbook?view#Downloading_and_Configuring_Sesame][Setting up to use the Sesame libraries]].
---++ Setup
---+++ Required Files
This tutorial assumes you have Virtuoso server installed and that the database is accessible
at
[[http://localhost:1111/][http://localhost:1111/]] . In addition, the relevant
version of the Virtuoso Sesame Provider, and Sesame java framework need to be installed.
You should download the Virtuoso Sesame Provider JAR archive for the version of Sesame being used, Virtuoso JDBC Driver, Sesame
Framework and associated classes and sample programs from our [[VOSDownload][download page]]. Note the version of the Sesame Provider (virt_sesameX.jar) can be determined with the command:
$ java -jar virt_sesame2.jar
OpenLink Virtuoso(TM) Provider for Sesame2(TM) Version 2.6.5 [Build 1.7]
$ java -jar virt_sesame4.jar
OpenLink Virtuoso(TM) Provider for Sesame4(TM) Version 4.0.0 [Build 0.1]
$
---+++ Sesame 2 Sample Program
---++++ Compilation
1 Ensure that full paths to the following files, or equivalents for your version of Sesame, are all included in the active CLASSPATH setting --
* openrdf-sesame-2.1.2-onejar.jar
* slf4j-api-1.5.0.jar
* slf4j-jdk14-1.5.0.jar
* commons-io-2.0.jar
* virtjdbc3.jar
* virt_sesame2.jar
1 Execute the following command --
javac VirtuosoTest.java
* Note: we recommend adding the following to the connect string, to use utf-8 and row-auto-commit:
"/charset=UTF-8/log_enable=2"
-- i.e., in VirtuosoTest.java , the line --
Repository repository = new VirtuosoRepository("jdbc:virtuoso://" + sa[0] + ":" + sa[1], sa[2], sa[3]);
-- should become --
Repository repository = new VirtuosoRepository("jdbc:virtuoso://" + sa[0] + ":" + sa[1]+ "/charset=UTF-8/log_enable=2", sa[2], sa[3]);
---++++ Testing
1 Ensure that full paths to the following files are all included in the active CLASSPATH
setting (note the addition of virtuoso_driver , here) --
* openrdf-sesame-2.1.2-onejar.jar
* slf4j-api-1.5.0.jar
* slf4j-jdk14-1.5.0.jar
* commons-io-2.0.jar
* virtjdbc3.jar
* virt_sesame2.jar
* virtuoso_driver
1 Run the [[http://virtuoso.openlinksw.com/dataspace/dav/wiki/Main/VirtSesame2Provider?att=VirtuosoTest.java][VirtuosoTest]]
program to test the Sesame 2 Provider with the following command --
java VirtuosoTest
1 The test run should look like this --
$ java VirtuosoTest localhost 1111 dba dba
== TEST 1: : Start
Loading data from URL: http://www.openlinksw.com/dataspace/person/kidehen@openlinksw.com/foaf.rdf
== TEST 1: : End
PASSED: TEST 1
== TEST 2: : Start
Clearing triple store
== TEST 2: : End
PASSED: TEST 2
== TEST 3: : Start
Loading data from file: virtuoso_driver/data.nt
== TEST 3: : End
PASSED: TEST 3
== TEST 4: : Start
Loading UNICODE single triple
== TEST 4: : End
PASSED: TEST 4
== TEST 5: : Start
Loading single triple
== TEST 5: : End
PASSED: TEST 5
== TEST 6: : Start
Casted value type
== TEST 6: : End
PASSED: TEST 6
== TEST 7: : Start
Selecting property
== TEST 7: : End
PASSED: TEST 7
== TEST 8: : Start
Statement does not exists
== TEST 8: : End
PASSED: TEST 8
== TEST 9: : Start
Statement exists (by resultset size)
== TEST 9: : End
PASSED: TEST 9
== TEST 10: : Start
Statement exists (by hasStatement())
== TEST 10: : End
PASSED: TEST 10
== TEST 11: : Start
Retrieving namespaces
== TEST 11: : End
PASSED: TEST 11
== TEST 12: : Start
Retrieving statement (http://myopenlink.net/dataspace/person/kidehen http://myopenlink.net/foaf/name null)
== TEST 12: : End
PASSED: TEST 12
== TEST 13: : Start
Writing the statements to file: (/Users/src/virtuoso-opensource/binsrc/sesame2/results.n3.txt)
== TEST 13: : End
PASSED: TEST 13
== TEST 14: : Start
Retrieving graph ids
== TEST 14: : End
PASSED: TEST 14
== TEST 15: : Start
Retrieving triple store size
== TEST 15: : End
PASSED: TEST 15
== TEST 16: : Start
Sending ask query
== TEST 16: : End
PASSED: TEST 16
== TEST 17: : Start
Sending construct query
== TEST 17: : End
PASSED: TEST 17
== TEST 18: : Start
Sending describe query
== TEST 18: : End
PASSED: TEST 18
============================
PASSED:18 FAILED:0
---+++ Sesame 4 Sample Program
---++++ Compilation
1 Ensure that full paths to the following files, or equivalents for your version of Sesame, are all included in the active CLASSPATH setting --
* openrdf-sesame-4.0.0-onejar.jar
* slf4j-api-1.7.10.jar
* commons-io-2.4.jar
* virtjdbc4.jar
* virt_sesame4.jar
1 Execute the following command --
javac VirtuosoTest.java
* Note: we recommend adding the following to the connect string, to use utf-8 and row-auto-commit:
"/charset=UTF-8/log_enable=2"
-- i.e., in VirtuosoTest.java , the line --
Repository repository = new VirtuosoRepository("jdbc:virtuoso://" + sa[0] + ":" + sa[1], sa[2], sa[3]);
-- should become --
Repository repository = new VirtuosoRepository("jdbc:virtuoso://" + sa[0] + ":" + sa[1]+ "/charset=UTF-8/log_enable=2", sa[2], sa[3]);
---++++ Testing
1 Ensure that full paths to the following files are all included in the active CLASSPATH
setting (note the addition of virtuoso_driver , here) --
* openrdf-sesame-4.0.0-onejar.jar
* slf4j-api-1.7.10.jar
* commons-io-2.4.jar
* virtjdbc4.jar
* virt_sesame4.jar
* virtuoso_driver
1 Run the [[http://download3.openlinksw.com/uda/virtuoso/rdfproviders/sesame/40/VirtuosoTest.java][VirtuosoTest]]
program to test the Sesame 2 Provider with the following command --
java VirtuosoTest
1 The test run should look like this --
$ java VirtuosoTest localhost 1111 dba dba
== TEST 1: : Start
== TEST 1: : End
PASSED: TEST 1
== TEST 2: : Start
Loading data from URL: http://dbpedia.org/data/Berlin.rdf
log4j:WARN No appenders could be found for logger (org.openrdf.rio.RDFParserRegistry).
log4j:WARN Please initialize the log4j system properly.
== TEST 2: : End
PASSED: TEST 2
== TEST 3: : Start
Clearing triple store
== TEST 3: : End
PASSED: TEST 3
== TEST 4: : Start
Loading data from file: virtuoso_driver/data.nt
== TEST 4: : End
PASSED: TEST 4
== TEST 5: : Start
Loading UNICODE single triple
== TEST 5: : End
PASSED: TEST 5
== TEST 6: : Start
Loading single triple
== TEST 6: : End
PASSED: TEST 6
== TEST 7: : Start
Casted value type
== TEST 7: : End
PASSED: TEST 7
== TEST 8: : Start
Selecting property
== TEST 8: : End
PASSED: TEST 8
== TEST 9: : Start
Statement does not exists
== TEST 9: : End
PASSED: TEST 9
== TEST 10: : Start
Statement exists (by resultset size)
== TEST 10: : End
PASSED: TEST 10
== TEST 11: : Start
Statement exists (by hasStatement())
== TEST 11: : End
PASSED: TEST 11
== TEST 12: : Start
Retrieving namespaces
== TEST 12: : End
PASSED: TEST 12
== TEST 13: : Start
Retrieving statement (http://myopenlink.net/dataspace/person/kidehen http://myopenlink.net/foaf/name null)
== TEST 13: : End
PASSED: TEST 13
== TEST 14: : Start
Writing the statements to file: (/Users/hwilliams/src/git/vos-7-develop/binsrc/sesame4/results.n3.txt)
== TEST 14: : End
PASSED: TEST 14
== TEST 15: : Start
Retrieving graph ids
== TEST 15: : End
PASSED: TEST 15
== TEST 16: : Start
Retrieving triple store size
== TEST 16: : End
PASSED: TEST 16
== TEST 17: : Start
Sending ask query
== TEST 17: : End
PASSED: TEST 17
== TEST 18: : Start
Sending construct query
== TEST 18: : End
PASSED: TEST 18
== TEST 19: : Start
Sending describe query
== TEST 19: : End
PASSED: TEST 19
============================
PASSED:19 FAILED:0
--++ Getting Started
This section covers the essentials for connecting to and manipulating data stored in a Virtuoso repository
using the Sesame API. More information on the Sesame Framework, including extended examples on how
to use the API, can be found in Chapter 8 of the Sesame User's guide,
[[http://www.openrdf.org/doc/sesame2/2.1.2/users/ch08.html#d0e833][the RepositoryConnection API]].
The interfaces for the Repository API can be found in packages virtuoso.sesame2.driver
and org.openrdf.repository . Several implementations for these interfaces exist in the
Virtuoso Provider download package. The [[http://www.openrdf.org/doc/sesame2/2.1.2/apidocs/][Javadoc reference for the Sesame API]]
is available online and can also be found in the doc directory of the download.
---+++Creating a Virtuoso Repository RDF object
The first step to connecting to Virtuoso through the Sesame API is to create a Repository for it. The
Repository object operates on (stacks of) Sail object(s) for storage and retrieval of RDF data.
One of the simplest configurations is a repository that just stores RDF data in main memory, without
applying any inference. This is also by far the fastest type of repository that can be used. The following
code creates and initialize a non-inferencing main-memory repository:
import virtuoso.sesame2.driver.VirtuosoRepository;
Repository myRepository = VirtuosoRepository("jdbc:virtuoso://localhost:1111","dba","dba");
myRepository.initialize();
The constructor of the VirtuosoRepository class accepts
the JDBC URL of the Virtuoso engine, and the username and password of an authorized user.
Following this example, the repository needs to be initialized to prepare the Sail(s) that it
operates on, which includes performing operations such as restoring previously stored data,
setting up connections to a relational database, etc.
The repository that is created by the above code is volatile: its contents are lost when the
object is garbage collected or when the program is shut down. This is fine for cases where,
for example, the repository is used as a means for manipulating an RDF model in memory.
---+++Creating a Virtuoso Repository Connection
Now that we have created a VirtuosoRepository object
instance, we want to do something with it. This is achieved through the use of the
VirtuosoRepositoryConnection class, which can be created
by the VirtuosoRepository class.
A VirtuosoRepositoryConnection represents — as
the name suggests — a connection to the actual Virtuoso quad store. We can issue
operations over this connection, and close it when we are done to make sure we are not
keeping resources unnecessarily occupied.
In the following sections, we will show some examples of basic operations using the Northwind
dataset.
---+++Adding RDF to Virtuoso
The Repository implements the Sesame Repository API, which offers various methods for adding
data to a repository. Data can be added programmatically by specifying the location of a file that
contains RDF data, and statements can be added individually or in collections.
We perform operations on the repository by requesting a RepositoryConnection
from the repository, which returns a VirtuosoRepositoryConnection object. On
this VirtuosoRepositoryConnection object we can perform the various operations,
such as query evaluation; getting, adding, or removing statements; etc.
The following example code adds two files, one local and one located on the Web, to a repository:
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.rio.RDFFormat;
import java.io.File;
import java.net.URL;
File file = new File("/path/to/example.rdf");
String baseURI = "http://example.org/example/localRDF";
?
try {
RepositoryConnection con = myRepository.getConnection();
try {
con.add(file, baseURI, RDFFormat.RDFXML);
URL url = new URL("http://example.org/example/remoteRDF");
con.add(url, url.toString(), RDFFormat.RDFXML);
}
finally {
con.close();
}
}
catch (RepositoryException rex) {
// handle exception
}
catch (java.io.IOEXception e) {
// handle io exception
}
More information on other available methods can be found in the javadoc reference of the
RepositoryConnection interface.
---+++Querying Virtuoso
The Repository API has a number of methods for creating and evaluating queries. Three
types of queries are distinguished: tuple queries, graph queries, and Boolean queries. The
query types differ in the type of results that they produce.
*Select Query*: The result of a select query is a set of tuples (or variable bindings), where
each tuple represents a solution of the query. This type of query is commonly used to get
specific values (URIs, blank nodes, literals) from the stored RDF data. The method
QueryFactory.executeQuery() returns a Value
[ ][ ] for SPARQL "SELECT " queries.
The method QueryFactory.executeQuery() also calls
the QueryFactory.setResult() which populates a set of
tuples for SPARQL "SELECT " queries. The graph can be retrieved using
QueryFactory.getBooleanResult() .
*Graph Query*: The result of a graph query is an RDF graph (or set of statements). This
type of query is very useful for extracting sub-graphs from the stored RDF data, which can
then be queried further, serialized to an RDF document, etc. The method
QueryFactory.executeQuery() calls the
QueryFactory.setGraphResult() which populates a graph
for SPARQL "DESCRIBE " and "CONSTRUCT " queries. The
graph can be retrieved using QueryFactory.getGraphResult() .
*Boolean Query*: The result of a Boolean query is a simple Boolean value, i.e., TRUE
or FALSE . This type of query can be used to check if a repository contains specific
information. The method QueryFactory.executeQuery() calls
the QueryFactory.setBooleanResult() which sets a Boolean value
for SPARQL "ASK " queries. The value can be retrieved using
QueryFactory.getBooleanResult() .
Note: Although Sesame 2 currently supports two query languages: SeRQL and SPARQL, the Virtuoso
provider only supports the W3C SPARQL specification at this time.
---+++Evaluating a SELECT Query
To evaluate a tuple query we simply do the following:
import java.util.List;
import org.openrdf.OpenRDFException;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.query.BindingSet;
import org.openrdf.query.QueryLanguage;
?
try {
RepositoryConnection con = myRepository.getConnection();
try {
String queryString = "SELECT x, y FROM WHERE {x} p {y}";
TupleQuery tupleQuery = con.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
TupleQueryResult result = tupleQuery.evaluate();
try {
? // do something with the result
}
finally {
result.close();
}
}
finally {
con.close();
}
}
catch (RepositoryException e) {
// handle exception
}
This evaluates a SPARQL query and returns a TupleQueryResult ,
which consists of a sequence of BindingSet objects. Each
BindingSet contains a set of pairs called Binding
objects. A Binding object represents a name/value pair for each
variable in the query's projection.
We can use the TupleQueryResult to iterate over all results and
get each individual result for x and y:
while (result.hasNext()) {
BindingSet bindingSet = result.next();
Value valueOfX = bindingSet.getValue("x");
Value valueOfY = bindingSet.getValue("y");
// do something interesting with the query variable values here?
}
As you can see, we retrieve values by name rather than by an index. The names used should be the names
of variables as specified in your query. The TupleQueryResult.getBindingNames()
method returns a list of binding names, in the order in which they were specified in the query. To process
the bindings in each binding set in the order specified by the projection, you can do the following:
List bindingNames = result.getBindingNames();
while (result.hasNext()) {
BindingSet bindingSet = result.next();
Value firstValue = bindingSet.getValue(bindingNames.get(0));
Value secondValue = bindingSet.getValue(bindingNames.get(1));
// do something interesting with the values here?
}
It is important to invoke the close() operation on the TupleQueryResult ,
after we are done with it. A TupleQueryResult evaluates lazily and keeps resources (such as connections
to the underlying database) open. Closing the TupleQueryResult frees up these resources. Do not forget
that iterating over a result may cause exceptions! The best way to make sure no connections are kept open unnecessarily is to invoke
close() in the finally clause.
An alternative to producing a TupleQueryResult is to supply an object that implements the
TupleQueryResultHandler interface to the query's evaluate()
method. The main difference is that when using a return object, the caller has control over when the next answer is retrieved,
whereas with the use of a handler, the connection simply pushes answers to the handler object as soon as it has them available.
As an example we will use SPARQLResultsXMLWriter , which is a
TupleQueryResultHandler implementation that writes SPARQL Results
XML documents to an output stream or to a writer:
import org.openrdf.query.resultio.sparqlxml.SPARQLResultsXMLWriter;
?
FileOutputStream out = new FileOutputStream("/path/to/result.srx");
try {
SPARQLResultsXMLWriter sparqlWriter = new SPARQLResultsXMLWriter(out);
RepositoryConnection con = myRepository.getConnection();
try {
String queryString = "SELECT * FROM WHERE {x} p {y}";
TupleQuery tupleQuery = con.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
tupleQuery.evaluate(sparqlWriter);
}
finally {
con.close();
}
}
finally {
out.close();
}
You can just as easily supply your own application-specific implementation of
TupleQueryResultHandler , if desired.
Lastly, an important warning: as soon as you are done with the RepositoryConnection
object, you should close it. Notice that during processing of the TupleQueryResult
object (for example, when iterating over its contents), the RepositoryConnection
should still be open. We can invoke con.close() after we have finished with the result.
---+++Evaluating a CONSTRUCT query
The following code evaluates a graph query on a repository:
import org.openrdf.query.GraphQueryResult;
GraphQueryResult graphResult = con.prepareGraphQuery(
QueryLanguage.SPARQL, "CONSTRUCT * FROM {x} p {y}").evaluate();
A GraphQueryResult is similar to TupleQueryResult
in that it is an object that iterates over the query results. However, for graph queries the query results are RDF statements,
so a GraphQueryResult iterates over Statement objects:
while (graphResult.hasNext()) {
Statement st = graphResult.next();
// ? do something with the resulting statement here.
}
The TupleQueryResultHandler equivalent for graph queries is
org.openrdf.rio.RDFHandler . Again, this is a generic interface;
each object implementing it can process the reported RDF statements in any way it wants.
All writers from Rio (such as the RDFXMLWriter ,
TurtleWriter , TriXWriter , etc.)
implement the RDFHandler interface. This allows them to be used
in combination with querying quite easily. In the following example, we use a
TurtleWriter to write the result of a SPARQL graph query to
standard output in Turtle format:
import org.openrdf.rio.turtle.TurtleWriter;
?
RepositoryConnection con = myRepository.getConnection();
try {
TurtleWriter turtleWriter = new TurtleWriter(System.out);
con.prepareGraphQuery(QueryLanguage.SPARQL, "CONSTRUCT * FROM WHERE {x} p {y}").evaluate(turtleWriter);
}
finally {
con.close();
}
Again, note that as soon as we are done with the result of the query (either after iterating over the
contents of the GraphQueryResult or after invoking the
RDFHandler ), we invoke con.close()
to close the connection and free resources.
---++ Javadoc API Documentation
Javadocs covers the complete set of classes, interfaces, and methods implemented by the provider:
* [[http://docs.openlinksw.com/sesame/][Javadoc API Documentation for the Sesame 2.6 Provider]]
* [[http://docs.openlinksw.com/sesame2/][Javadoc API Documentation for the Sesame 2.7+ Provider]]
* [[http://docs.openlinksw.com/sesame4/][Javadoc API Documentation for the Sesame 4.x Provider]]
---++Related
* [[VirtSesame2HttpRepository][Virtuoso Sesame HTTP Repository]]
CategoryRDF CategoryOpenSource CategoryVirtuoso CategoryVOS CategorySesame CategoryDocumentation
%VOSCOPY% |