<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>2Paths &#187; triples</title>
	<atom:link href="http://www.2paths.com/tag/triples/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.2paths.com</link>
	<description>Custom Software Technical Architecture, Design and Development in Vancouver, BC, Canada</description>
	<lastBuildDate>Mon, 27 Sep 2010 01:15:46 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Mulgara RDF Triple-Store</title>
		<link>http://www.2paths.com/2008/12/30/mulgara-rdf-store/</link>
		<comments>http://www.2paths.com/2008/12/30/mulgara-rdf-store/#comments</comments>
		<pubDate>Tue, 30 Dec 2008 20:45:29 +0000</pubDate>
		<dc:creator>Omar</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jena]]></category>
		<category><![CDATA[jrdf]]></category>
		<category><![CDATA[mulgara]]></category>
		<category><![CDATA[rdf store]]></category>
		<category><![CDATA[rmi]]></category>
		<category><![CDATA[semantic web]]></category>
		<category><![CDATA[triples]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=437</guid>
		<description><![CDATA[Over the past 4 months I have intermittently been looking into the use of the Mulgara RDF triple store. Mulgara is an open-source RDF triple store that boasts to be able to handle up to 7 Billion nodes and was developed some big players in the semantic web space (Zepheira, Topaz and Fedora Commons). My [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past 4 months I have intermittently been looking into the use of the Mulgara RDF triple store. Mulgara is an open-source RDF triple store that boasts to be able to handle up to 7 Billion nodes and was developed some big players in the semantic web space (Zepheira, Topaz and Fedora Commons). My intention was to see if it could be of use in future projects as an alternative to a traditional database.</p>
<h3>RDF</h3>
<p>For those who are unfamilar with RDF a short description would be:</p>
<blockquote><p>The Resource Description Framework (RDF) is a language for     representing information about resources in the World Wide Web.     This Primer is designed to provide the reader with the basic     knowledge required to effectively use RDF. It introduces the basic concepts of RDF and describes its XML syntax. It describes how to define RDF vocabularies using the RDF Vocabulary Description     Language, and gives an overview of some deployed RDF applications.     It also describes the content and purpose of other RDF specification documents.</p></blockquote>
<p>For more information about RDF read the <a title="RDF Primer" href="http://www.w3.org/TR/rdf-primer/">following primer</a> hosted on the W3C&#8217;s website.</p>
<h3>RDF Stores</h3>
<p>An RDF store allows for flexible definition of content which is a shortcoming of traditional relational database. An example of this would be the need to add a field within a database. In a relational database one would have to define a new column in the database table which is not usually achievable from a program given that most systems are not foolish to allow database changes from code. However, in an RDF data-store things are stored as nodes and relationships between nodes. Therefore to add a new field simply requires that a new node be created and an establishment of a relationship between the existing nodes and the new node. This flexibility is extremely handy in cases where the data being captured by a system changes often. Add to this the creation of an RDF schema or an ontology and one has the ability to semantically query the data you have within your data-store and are able to make use of meta-data in a way that can not be done within a relational database.</p>
<p>I was thinking that this type of flexibility would be of great benefit for a project we hope to be working on in the new year. Given Zephira&#8217;s backing of Mulgara I thought I would investigate whether it could be ready for prime time and the level of complexity required in using it.</p>
<h3>Mulgara</h3>
<p>Mulgara was initiated in 2006 and was a fork of the <a href="http://sourceforge.net/projects/kowari/">Kowari project</a> which died or became unsupported as of 2005. Their claim is that Mulgara has the following featured:</p>
<ul>
<li>Native RDF support</li>
<li>Multiple databases (models) per server</li>
<li>Simple SQL-like query language</li>
<li>Small footprint</li>
<li>Full text search functionality</li>
<li>Datatype support</li>
<li>Supports and tracks W3C Specifications and guidelines</li>
<li>Large storage capacity</li>
<li>Optimized for metadata storage and retrieval</li>
<li>Multi-processor support</li>
<li>Independently tuned for both 64-bit and 32-bit architectures</li>
<li>Low memory requirements</li>
<li>On-disk joins</li>
<li>Streamed query results</li>
</ul>
<p>The remainder of this post will cover my experiences with using Mulgara.</p>
<h3>Rough Start</h3>
<p>Unfortunately things didn&#8217;t start off well.  Though the downloading and installation of the Mulgara server was painless there were a number of issues that I came across that would deter many from considering the use of it in a production level system:</p>
<h4>Connectors are not included in the default download</h4>
<p>Currently there are only a few means of accessing Mulgara to perform CRUD operations:</p>
<ul>
<li>A <a title="JRDF" href="http://jrdf.sourceforge.net/">JRDF</a> connector</li>
<li>A <a title="Jena Semantic Framework" href="http://jena.sourceforge.net/">Jena</a> connector</li>
<li>Straight RMI (remote method invocation)</li>
</ul>
<p>In the default download from the Mulgara website, the JRDF and Jena connectors are not provided. After a lot of struggling, I resorted to downloading the source and building the server from scratch to ensure that the connectors were included within the jar files.</p>
<p>After getting to this stage I tried to follow the tutorials to try and connect and interact with the server. It seems that the documentation on the mulgara website is stale and that they have not been able to keep their tutorials up to date because the code provided in them does not work unless one uses an in-memory database which is not specified in the tutorial. I posted questions to the various user group email lists and receive no responses.</p>
<p>Once I figured those aspects out things went more smoothly though there is a significant amount of boiler plate code that needs to be created to allow for simple CRUD operations.</p>
<h3>Creating a connection to the server</h3>
<p>As noted above, one can not simply use JDBC to connect to the server but have an option of using the majority of the popular RDF creation frameworks such as JRDF, Jena or Sesame. I initially tired to use Jena but it seems that support for the <a title="JenaMulgara connector" href="http://jena.hpl.hp.com/wiki/JenaMulgara">JenaMulgara connector</a> died quite a while ago and the connector does not work for the latest version of Mulgara. Therefore, I moved on to the JRDF connector given that the Sesame connector is quite immature.</p>
<pre class="brush: java">
// Create the URI of the server
java.net.URI serverURI = new java.net.URI(&quot;rmi&quot;, hostName, &quot;/&quot; + serverName, null);</pre>
<p>// Create a new session factory, ensure that it&#8217;s local<br />
SessionFactory sessionFactory = SessionFactoryFinder.newSessionFactory(serverURI, false);</p>
<p>// Get a local JRDF Session (local)<br />
Object o = sessionFactory.newJRDFSession();<br />
org.mulgara.server.JRDFSession session = (JRDFSession) sessionFactory.newJRDFSession();<br />
[/sourcecode]</p>
<h3>Create a model/database</h3>
<p>The above give you a connection to the Mulgara server. To create a model/database requires the following section of code:</p>
<pre class="brush: java">
java.net.URI modelURI = new URI(&quot;rmi&quot;, hostName, &quot;/&quot; + serverName, graphName);
java.net.URI modelType = new URI(&quot;http://mulgara.org/mulgara#Model&quot;);
session.createModel(modelURI, modelType);
org.jrdf.graph.Graph graph = ClientGraph(createGraphProxy(modelURI, session));
</pre>
<h3>Create nodes/relationships</h3>
<p>In order to create RDF triples one needs to specify a subject, predicate and an object. There are three types of Java objects that can be used in this in building these relationships:</p>
<ol>
<li>BlankNode &#8211; a blank node that is a node used to group other relationships. A BlankNode can be used as either a subject or an object</li>
<li>Literal &#8211; a literal value of some sort (String, number, etc.) A literal can only be used as an object and not a subject or predicate</li>
<li>URIReference &#8211; a URIReference is used to define the predicate or relationship between the subject and the object.</li>
</ol>
<pre class="brush: java">
org.jrdf.graph.GraphElementFactory elementFactory = graph.getElementFactory();
org.jrdf.graph.BlankNode blanknode = elementFactory.createResource();
org.jrdf.graph.URIReference predicate = elementFactory.createResource(new URI());
org.jrdf.graph.Literal literal = elementFactory.createLiteral(value);
</pre>
<p>Lastly to create and insert a triple one simply needs to do the following:</p>
<pre class="brush: java">
org.jrdf.graph.Triple triple = elementFactory.createTriple(subject, predicate, object); // Create the triple object
graph.add(triple); // Store the triple in Mulgara server
</pre>
<p>For sample code on how to do everything from connect to query and delete see the end of this post.</p>
<h3>Performance</h3>
<p>I wrote a simple application that took the contents of a relational database and converted it into RDF and stored it in Mulgara. The database I was using was big but not huge, roughly &#8230;. All these numbers are based on running the application on a MacBook Pro with a 2Gh Core Duo processor and 2GB of RAM. I initially wrote the app to do inserts one at a time which was obviously inefficient but I wanted to test out the speed of an insert. Each insert of a single triple took roughly 0.17 seconds. In round 2 I started doing inserts in batch. In batch mode it seems that inserts took roughly 0.08 seconds per insert of a node. Both speeds are not particularly fast but like I said, this is running off my laptop so one can&#8217;t expect superb performance.</p>
<h3>Conclusion</h3>
<p>Given that RDF stores are competing with regular relational databases I would have hoped that there was an easier means of connecting to the database and that RM wasn&#8217;t being used under the hood. Given the push for RESTful interfaces within the semantic world, I was surprised to see that the Mulgara server does not have a RESTful interface which would relieve the need for RMI completely. Once I got over my dependence on the abhorrent tutorials and documentation things went fairly well though I have performance concerns when dealing with large volumes of data. The main area of concern for me is the requirement of RMI which has been well documented as being not very performant. It pains me to have to use RMI when running both the server and the application on the same server. What is nice is that the server is completely transactional and any failure results in a roll-back. The last concern I have is the fact that the user community/group around Mulgara does not seem to be very active or dedicated to ensuring that the product is supported to the extent that one can rely on getting up to date documentation and a steady stream of bug fixes.</p>
<h3>Sample Code</h3>
<p>The following code sample shows how to perform inserts, updates, deletes and selection.</p>
<pre class="brush: java">
package org.twopaths.jrdf;

import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;

import org.jrdf.graph.BlankNode;
import org.jrdf.graph.Graph;
import org.jrdf.graph.GraphElementFactory;
import org.jrdf.graph.GraphElementFactoryException;
import org.jrdf.graph.GraphException;
import org.jrdf.graph.Literal;
import org.jrdf.graph.Triple;
import org.jrdf.graph.URIReference;
import org.jrdf.util.ClosableIterator;
import org.mulgara.client.jrdf.AbstractGraphFactory;
import org.mulgara.query.QueryException;
import org.mulgara.server.JRDFSession;
import org.mulgara.server.NonRemoteSessionException;
import org.mulgara.server.SessionFactory;
import org.mulgara.server.driver.SessionFactoryFinder;
import org.mulgara.server.driver.SessionFactoryFinderException;

public class Sandbox {
	public static void main(String[] args) {
                Graph graph = null;
		try {
			// Create the host name
			String hostname = InetAddress.getLocalHost().getCanonicalHostName();

			// Create the URI of the server
			URI serverURI = new URI(&quot;rmi&quot;, hostname, &quot;/&quot; + &quot;server1&quot;, null);

			// Create a new session factory, ensure that it&#039;s local
			SessionFactory sessionFactory = SessionFactoryFinder.newSessionFactory(serverURI, false);

			// Get a local JRDF Session (local)
			Object o = sessionFactory.newJRDFSession();
			System.out.println(o.getClass().getName());
//			LocalJRDFSession session = (LocalJRDFSession) sessionFactory.newJRDFSession();
			JRDFSession session = (JRDFSession) sessionFactory.newJRDFSession();

			//create a new Model
			URI modelURI = new URI(&quot;rmi&quot;, hostname, &quot;/&quot; + &quot;server1&quot;, &quot;exampleGraph&quot;);
			URI modelType = new URI(&quot;http://mulgara.org/mulgara#Model&quot;);
			session.createModel(modelURI, modelType);

			//create a JRDF Graph for the model
//			graph = new JRDFGraph(session, modelURI);
			graph = AbstractGraphFactory.createGraph(serverURI, modelURI);

			//get the Factory
			GraphElementFactory elementFactory = graph.getElementFactory();

			//create resources
			URIReference person = elementFactory.createResource(new URI(&quot;http://example.org/staffid#85740&quot;));
			BlankNode address = elementFactory.createResource();

			//create properties
			URIReference hasAddress = elementFactory.createResource(new URI(&quot;http://example.org/terms#address&quot;));
			URIReference hasStreet = elementFactory.createResource(new URI(&quot;http://example.org/terms#street&quot;));
			URIReference hasCity = elementFactory.createResource(new URI(&quot;http://example.org/terms#city&quot;));
			URIReference hasState = elementFactory.createResource(new URI(&quot;http://example.org/terms#state&quot;));
			URIReference hasPostCode = elementFactory.createResource(new URI(&quot;http://example.org/terms#postalCode&quot;));

			//create values
			Literal street = elementFactory.createLiteral(&quot;1501 Grant Avenue&quot;);
			Literal city = elementFactory.createLiteral(&quot;Bedford&quot;);
			Literal state = elementFactory.createLiteral(&quot;Massachusetts&quot;);
			Literal postCode = elementFactory.createLiteral(&quot;01730&quot;);

			//create statements
			Triple addressStatement = elementFactory.createTriple(person, hasAddress, address);
			Triple streetStatement = elementFactory.createTriple(address, hasStreet, street);
			Triple cityStatement = elementFactory.createTriple(address, hasCity, city);
			Triple stateStatement = elementFactory.createTriple(address, hasState, state);
			Triple postCodeStatement = elementFactory.createTriple(address, hasPostCode, postCode);

			// Add triples to graph
			graph.add(addressStatement);
			graph.add(streetStatement);
			graph.add(cityStatement);
			graph.add(stateStatement);
			graph.add(postCodeStatement);

			//get all Triples
			Triple findAll = elementFactory.createTriple(null, null, null);
			ClosableIterator allTriples = graph.find(findAll);
			while (allTriples.hasNext()) {
				System.out.println(allTriples.next().toString());
			}

			//search for address (as a subject)
			Triple findAddress = elementFactory.createTriple(address, null, null);
			ClosableIterator addressSubject = graph.find(findAddress);
			while (addressSubject.hasNext()) {
				System.out.println(addressSubject.next().toString());
			}

			//search for the city: &quot;Bedford&quot;
			Triple findCity = elementFactory.createTriple(null, null, city);
			ClosableIterator bedfordCity = graph.find(findCity);
			while (bedfordCity.hasNext()) {
				System.out.println(bedfordCity.next().toString());
			}

			//search for any subject that has an address
			Triple findAddresses = elementFactory.createTriple(null, hasAddress, null);
			ClosableIterator addresses = graph.find(findAddresses);
			while (addresses.hasNext()) {
				System.out.println(addresses.next().toString());
			}

		} catch (UnknownHostException uhe) {
			uhe.printStackTrace();
		} catch (URISyntaxException urise) {
			urise.printStackTrace();
		} catch (SessionFactoryFinderException sffe) {
			sffe.printStackTrace();
		} catch (NonRemoteSessionException nrse) {
			nrse.printStackTrace();
		} catch (QueryException qe) {
			qe.printStackTrace();
		} catch (GraphException ge) {
			ge.printStackTrace();
		} catch (GraphElementFactoryException gefe) {
			gefe.printStackTrace();
		} finally {
                        try {
                            graph.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                }
		System.out.println(&quot;DONE&quot;);
	}
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/30/mulgara-rdf-store/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

