<?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"
	>

<channel>
	<title>2Paths</title>
	<atom:link href="http://www.2paths.com/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>
	<pubDate>Sun, 04 Jan 2009 16:14:13 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<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[semantic web]]></category>

		<category><![CDATA[tech]]></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[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="syntax-highlight:java">
// Create the URI of the server
<a href="http://java.net" title="http://java.net" class="autohyperlink" target="_blank">java.net</a>.URI serverURI = new <a href="http://java.net" title="http://java.net" class="autohyperlink" target="_blank">java.net</a>.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="syntax-highlight:java">
<a href="http://java.net" title="http://java.net" class="autohyperlink" target="_blank">java.net</a>.URI modelURI = new URI(&quot;rmi&quot;, hostName, &quot;/&quot; + serverName, graphName);
<a href="http://java.net" title="http://java.net" class="autohyperlink" target="_blank">java.net</a>.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 - 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 - 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 - a URIReference is used to define the predicate or relationship between the subject and the object.</li>
</ol>
<pre class="syntax-highlight: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="syntax-highlight: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="syntax-highlight:java">
package org.twopaths.jrdf;

import <a href="http://java.net" title="http://java.net" class="autohyperlink" target="_blank">java.net</a>.InetAddress;
import <a href="http://java.net" title="http://java.net" class="autohyperlink" target="_blank">java.net</a>.URI;
import <a href="http://java.net" title="http://java.net" class="autohyperlink" target="_blank">java.net</a>.URISyntaxException;
import <a href="http://java.net" title="http://java.net" class="autohyperlink" target="_blank">java.net</a>.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>
		</item>
		<item>
		<title>Building GRAILS app on Debian using Maven GRAILS Plugin</title>
		<link>http://www.2paths.com/2008/12/23/building-grails-app-on-debian-using-maven-grails-plugin/</link>
		<comments>http://www.2paths.com/2008/12/23/building-grails-app-on-debian-using-maven-grails-plugin/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 23:07:54 +0000</pubDate>
		<dc:creator>Lorill</dc:creator>
		
		<category><![CDATA[Blog]]></category>

		<category><![CDATA[Technology under the hood]]></category>

		<category><![CDATA[development]]></category>

		<category><![CDATA[tech]]></category>

		<category><![CDATA[utilities]]></category>

		<category><![CDATA[debian]]></category>

		<category><![CDATA[Grails]]></category>

		<category><![CDATA[Grails ended with a non null return code]]></category>

		<category><![CDATA[grails maven plugin]]></category>

		<category><![CDATA[hudson]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=432</guid>
		<description><![CDATA[We&#8217;re now using GRAILS in one of our Maven-ized projects, and have it building using the Maven GRAILS plugin. We needed to roll this integration out to Husdon, our CI server which is running on a Debian box. We ran into a couple of snags.  
We had downloaded and installed the debian package grails_1.0.4-1_all.deb [...]]]></description>
			<content:encoded><![CDATA[<p>We&#8217;re now using GRAILS in one of our Maven-ized projects, and have it building using the <a href="http://forge.octo.com/maven/sites/mtg/grails-maven-plugin/">Maven GRAILS plugin</a>. We needed to roll this integration out to Husdon, our CI server which is running on a Debian box. We ran into a couple of snags.  </p>
<p>We had downloaded and installed the debian package <code>grails_1.0.4-1_all.deb</code> from the <a href="http://grails.org/Download">GRAILS site</a>, configured the GRAILS_HOME environment variable for our build target, and attempted to  build it. We got this error:<br />
<code>Grails ended with a non null return code: 127</code><br />
After some digging, it turns out that the debian package installs GRAILS but puts the actual executable in /usr/bin instead of just a symlink from the GRAILS_HOME.  The Maven GRAILS plugin appears to be calling grails using the GRAILS_HOME path. Making a symlink to the grails executable in the bin dir of the GRAILS_HOME fixed this problem (although the symlink really more correctly belongs in the /usr/bin dir).</p>
<p>Trying to build again we came across a different problem, where the GRAILS version was showing up as null, causing build errors. After some googling I found <a href="http://code.google.com/p/ant-deb-task/issues/detail?id=19#c1">this useful post</a>, and re-installed GRAILS with the updated <a href="http://code.google.com/p/ant-deb-task/downloads/detail?name=grails_1.0.4-2_all.deb&amp;can=2&amp;q=">grails_1.0.4-2_all.deb</a> package, repeating the steps for the GRAILS executable.  Now we&#8217;re all up and running in Hudson!  I hope this might alleviate some pain for anyone trying to troubleshoot this problem.</p>]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/23/building-grails-app-on-debian-using-maven-grails-plugin/feed/</wfw:commentRss>
		</item>
		<item>
		<title>LiquiBase-ifying your Grails Application</title>
		<link>http://www.2paths.com/2008/12/23/liquibase-ifying-your-grails-application/</link>
		<comments>http://www.2paths.com/2008/12/23/liquibase-ifying-your-grails-application/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 21:46:27 +0000</pubDate>
		<dc:creator>Lorill</dc:creator>
		
		<category><![CDATA[Technology under the hood]]></category>

		<category><![CDATA[development]]></category>

		<category><![CDATA[tech]]></category>

		<category><![CDATA[utilities]]></category>

		<category><![CDATA[database]]></category>

		<category><![CDATA[database developement]]></category>

		<category><![CDATA[database management]]></category>

		<category><![CDATA[Grails]]></category>

		<category><![CDATA[LiquiBase]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=401</guid>
		<description><![CDATA[At 2Paths we&#8217;ve got some pretty good processes in place: we practice agile software development and scrum, have all our projects set up in Continuous Integration. We try to do test-driven development where at all possible. One area that has slipped through the cracks though is database change management. What company hasn&#8217;t run into the [...]]]></description>
			<content:encoded><![CDATA[<p>At 2Paths we&#8217;ve got some pretty good processes in place: we practice agile software development and scrum, have all our projects set up in Continuous Integration. We try to do test-driven development where at all possible. One area that has slipped through the cracks though is database change management. What company hasn&#8217;t run into the problem of ensuring all database environments in a project (dev, staging, production, test) are in sync and in source control? Without this, it becomes an onerous if not impossible task to rollback a set of databases to a known state, or to recreate one from scratch to a known state.</p>
<p>Enter <a href="http://liquibase.org">LiquiBase</a>, an open source database-agnostic tool for tracking, managing and applying database changes. We recently worked on a small Grails project and decided to give this tool a try and I was duly impressed.</p>
<p>LiquiBase functionality is built around a main changelog.xml file containing changesets representing incremental database changes to be applied to a database. LiquiBase manages which changesets have been run through a DATABASECHANGELOG table it creates in each database. </p>
<p>We used the <a href="http://www.liquibase.org/manual/grails">grails plugin</a> which gave us most of the full LiquiBase functionality, albeit a little less than mature.  There were a couple of gotchas and bugs with the plugin, but nothing we couldn&#8217;t work around.</p>
<p>LiquiBase buys us the ability to store database change in source control, easily sync databases in multi-environments in an automated and controlled fashion, tag database states upon iteration-end releases, auto-generate rollback sql to tagged states, diff databases, and much more.</p>
<h2>LiquiBase-ifying Your Application</h2>
<p>With your database in a known state, you can use the grails plugin to create your changelog.xml. First you need to install the grails LiquiBase plugin:<br />
<code>grails install-plugin liquibase</code><br />
Once installed simply run this from the root of your grails app:<br />
<code>grails generate-changelog grails-app/changelog.xml</code></p>
<p>This will generate the changelog.xml from your development database (specified in DataSource.groovy) and write it to the path specified in the command.  <code>grails-app/changelog.xml</code> is the default path where the grails plugin will be expecting the changelog to be. If you need to read from a different database environment like staging for example, just add the -Dgrails.env=staging option to the command.</p>
<p>To propagate this changelog to other databases (say, test), run<br />
<code>grails -Dgrails.env=test migrate</code>. This runs all the sql necessary to upate the database to match the changelog. Any new changes from here on will be appended as new changesets, and can be migrated with the same command as above.  You can also use the migrate-sql command instead if want to generate the sql and run it yourself.  Most LiquiBase commands come in tuples: one to generate the sql for you and one to just run the sql directly against your database.</p>
<p>If you&#8217;re integrating LiquiBase mid-project and already have all your databases set up, you&#8217;ll need to run sql against them to update the LiquiBase DATABASECHANGELOG table to show all the changes as run.  First, make sure that the databases are all in sync. To do this, you can use the handy LiquiBase diff tool. Unfortunately, the grails plugin for this diff tool is not very robust and will only diff your development database against your test database - the plugin has those two environments hard-coded. You can either mess with your DataSource.groovy db environments to do the diff setting the two dbs in question to dev and test temporarily, or <a href="http://www.liquibase.org/download">install LiquiBase</a> itself and run the <a href="http://www.liquibase.org/manual/diff">diff</a> passing the db parameters to the diff command. Using the grails plugin you would run:<br />
<code>grails db-diff</code> which will spit to the screen any differences as changesets to be applied. Strangely, there is no documentation for this command in the <a href="http://www.liquibase.org/manual/grails">LiquiBase Grails plugin page</a>.</p>
<p>Once your database are in sync, run<br />
<code>grails changelog-sync-sql</code> with the appropriate <code>-Dgrails.env</code> switch to generate the sql to update the DATABASECHANGELOG table, then run the sql in your database.</p>
<h2>LiquiBase and Continuous Integration</h2>
<p>We use Hudson at 2Paths for our CI, and have added the simple <code>grails -Dgrails.env=test migrate</code> command as part of our build process to migrate the test database upon every checkin. This ensures that the test db is always the most up-to-date.</p>
<h2>Rolling LiquiBase into our Dev Process</h2>
<p>We&#8217;ve adopted on a trial basis the following process for database change management as part of our agile software development, taking into consideration Grails development (which uses hibernate) which can auto-generates schemas based on domain objects:</p>
<ol>
<li>Generate changelog from initial schema and commit to svn</li>
<li>Rollout schema to other databases by migrating from changelog</li>
<ol>
<li>if the schema already exists and it needs &#8220;LiquiBase-ifying&#8221;, generate changelog-sync-sql and run it</li>
</ol>
<li>Add every schema change via new changeset from hereon in by generating changelogs via grails <a href="http://www.liquibase.org/manual/diff">db-diff</a></li>
<ol>
<li>add / change domain objects in project</li>
<li>set hiberante ddl mode to update</li>
<li>start app and grails will automatically update the db</li>
<li>generate new changelogs using db-diff (against the test db)</li>
<li>append changelogs to changelog.xml</li>
<li>run <code>grails changelog-sync-sql</code> to generate the sql that will mark all these new changes as ran on your db, then run the sql</li>
<li>checkin changes. this will be applied to test</li>
</ol>
<li>provide explicit rollback sql for any custom sql</li>
<li>tag each iteration end with a &#8220;tagDatabase&#8221; changelog in the changelog.xml</li>
</ol>
<h2>Gotchas</h2>
<p>We ran into some gotchas with LiquiBase. One of the first things we started doing before fully understanding how LiquiBase worked was to update existing changesets when changing the schema. LiquiBase generates checksums for each changeset to ensure they don&#8217;t change, and altering existing changelogs will cause future migrations to fail. Even though LiquiBase gives you some tools to get around this, it&#8217;s generally a better practice to just add a new changeset for every database change. There is a good blog on the LiquiBase site explaining  <a href="http://blog.liquibase.org/2008/10/dealing-with-changing-changesets.html">how to deal with changing changesets</a>.</p>
<p>Another gotcha is that the rollback-sql command won&#8217;t magically generate rollback scripts for hand-coded sql (obviously!) You must to generate your own rollback sql for these custom sql tags, otherwise not only will you not get rollback sql for those particular changesets, but the rollback functionality won&#8217;t spit out sql for any other changeset either until you do.</p>
<p>Tagging was a little fussy as well. The command line <code>grails tag</code> can only tag a given state once - future tags will overwrite the earlier ones unless you&#8217;re at a different changeset. I found it better to add a tag changeset explicitly in the changelog.xml. The Grails plugin for tagging also seems to be problematic with spaces in the tag name. We decided to just use underscores as a convention.</p>
<p>We also ran across some broken functionality:</p>
<ul>
<li>The <code>grails generate-changelog</code> command generates some extraneous information that breaks sql for data type numeric(19,0) if that type has auto-increment on.  It generates this in the changelog:<br />
&lt;column autoIncrement=&#8221;true&#8221; name=&#8221;id&#8221; type=&#8221;numeric()(19,0)&#8221;&gt; (notice the extra empty brackets).  We needed to manually remove these to get it to work.</li>
<li>The <code>grails rollback-to-date-sql</code> command writes to a file with the datestamp instead of to console like the other rollbacks do, even though the docs say it writes to STDOUT (<code>rollback-count-sql</code> also has issues, but <code>rollback-sql</code> for tags works just fine). The code for these plugin commands doesn&#8217;t seem to do the right thing with the args. Time permitting, we may provide a patch for this.</li>
<li>db-doc generation doesn&#8217;t work with large amount of columns in a table because it uses the table description including column names for the html file name.  Too many db columns make the file names too long.</li>
</ul>
<h2>Moving Forward</h2>
<p>Although there&#8217;s a bit of grumbling amongst the developers here that using LiquiBase with the above process is a little onerous, it buys us a lot more certainty for knowing what state our databases are in, making sure changes are in source control, and knowing what updates have or haven&#8217;t been run. It&#8217;s a whole lot easier than hand-coding a bunch of sql, and easily accommodates the possibility of migrating to other DBMS&#8217;s in the future without having to re-write DBMS-specific sql. There&#8217;s even talk of trying to go a step or two further to automate even more of the process so a developer doesn&#8217;t have to think about generating changesets upon changing of a grails domain model. We&#8217;ll see how that goes.</p>]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/23/liquibase-ifying-your-grails-application/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Winter at Waterfall</title>
		<link>http://www.2paths.com/2008/12/22/winter-at-waterfall/</link>
		<comments>http://www.2paths.com/2008/12/22/winter-at-waterfall/#comments</comments>
		<pubDate>Tue, 23 Dec 2008 06:46:51 +0000</pubDate>
		<dc:creator>Aaron</dc:creator>
		
		<category><![CDATA[burbles]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=389</guid>
		<description><![CDATA[Vancouver received, well, alot of snow for Vancouver.  People always say we get alot of rain.  Think of that rain in a &#8220;snow-like form&#8221; and you get a sense of the volume/intensity.
So, needless to say it was a gong-show out there.  Those coming to work from further afield naturally called to say [...]]]></description>
			<content:encoded><![CDATA[<p>Vancouver received, well, alot of snow for Vancouver.  People always say we get alot of rain.  Think of that rain in a &#8220;snow-like form&#8221; and you get a sense of the volume/intensity.</p>
<p>So, needless to say it was a gong-show out there.  Those coming to work from further afield naturally called to say they wouldn&#8217;t be making it in.  This was Kari&#8217;s bus, stuck and blocking the road:</p>
<p><a href="http://www.flickr.com/photos/alutii/3128918552/" title="Bus stuck in Vancouver by Aaron Gladders, on Flickr"><img src="http://farm4.static.flickr.com/3283/3128918552_3a366899d9.jpg" width="500" height="375" alt="Bus stuck in Vancouver" /></a></p>
<p>The snow did this neat thing on the gallery space:</p>
<p><a href="http://www.flickr.com/photos/alutii/3128126727/" title="Winter at Waterfall by Aaron Gladders, on Flickr"><img src="http://farm4.static.flickr.com/3238/3128126727_83375c19d7.jpg" width="500" height="375" alt="Winter at Waterfall" /></a></p>
<p>The BBQ&#8217;s are buried:</p>
<p><a href="http://www.flickr.com/photos/alutii/3129244908/" title="Winter at Waterfall by Aaron Gladders, on Flickr"><img src="http://farm4.static.flickr.com/3221/3129244908_ba854c7a0e.jpg" width="500" height="375" alt="Winter at Waterfall" /></a></p>
<p>The rest of the shots are in a small set &#8220;<a href="http://flickr.com/photos/alutii/sets/72157611457571789/">Winter at Waterfall</a>&#8221; and the 360 is below:</p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/MoULXmRN1sA&#038;hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/MoULXmRN1sA&#038;hl=en&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/22/winter-at-waterfall/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Holidays, making an impact and creative capitalism</title>
		<link>http://www.2paths.com/2008/12/16/holidays-trying-to-make-an-impact-and-creative-capitalism/</link>
		<comments>http://www.2paths.com/2008/12/16/holidays-trying-to-make-an-impact-and-creative-capitalism/#comments</comments>
		<pubDate>Tue, 16 Dec 2008 18:31:23 +0000</pubDate>
		<dc:creator>Aaron</dc:creator>
		
		<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=378</guid>
		<description><![CDATA[Over the past year we’ve been involved with several projects and initiatives that will have a global impact on aid transparency and effectiveness.  They revolve around high level flows of funds from donor to recipient countries, even to the specific projects that are happening.  It&#8217;s pretty heady stuff.  With the holidays we [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past year we’ve been involved with several projects and initiatives that will have a global impact on aid transparency and effectiveness.  They revolve around high level flows of funds from donor to recipient countries, even to the specific projects that are happening.  It&#8217;s pretty heady stuff.  With the holidays we were faced with the usual company decision - should we spend some money on beautiful cards and give our friends a personal touch?  Or should we go the other route and donate the funds?  We of course went with the latter.  We can always do more or go deeper, but it is a chance to do something that can have a bit more of an impact &#8220;closer to the ground&#8221;.  We hope it may inspire you to do the same.</p>
<p>So - who to give to?  We wanted to make sure they would have an actual impact.  We decided on two broad areas.  I used to be a wildlife biologist in another life and one organization that stood out was <a href="http://www.conservation.org/">Conservation International</a>.  They have several areas of concern - to save species, conserve landscapes and seascapes, and empower communities with responsible  and effective use of natural resources.  It&#8217;s not just about preserving what&#8217;s out there in its current form; it&#8217;s about making sure it&#8217;s there in a sustainable way, involving the people who live there.  We donated $5,000.00 and &#8220;saved&#8221; about <a href="http://www.conservation.org/act/get_involved/protect_forests/Pages/deforestation.aspx">333 acres</a>.</p>
<p>The other organization we selected this year is <a href="http://www.kiva.org/">Kiva</a> whose mission is to connect people through lending for the sake of alleviating poverty. Kiva, from its partner organizations, puts forward entrepreneurs from the developing world, how much money they need and for what purpose in the hopes of connecting you to them.  It&#8217;s effectively a loan that will get paid back, although not necessarily.  With any luck we will though, and we can loan it to other entrepreneurs and it will keep &#8220;paying a dividend&#8221; if you will.  We&#8217;re trying to choose individuals/groups who want to build their business by either setting up infrastructure or creating new opportunities for themselves.  Again, we&#8217;ve put $5,000.00 towards this.</p>
<p>The thinking behind these choices was to live a form of creative capitalism - making the world a better place hopefully in a sustainable way.  We&#8217;ve been trying to live that in our company as well, through the clients we&#8217;ve been able to work with and the ones we hope to in the future.  If you agree with this notion and decide to lend or donate yourself, we hope you&#8217;ll let us know by dropping us an email (giving @ <a href="http://2paths.com" title="http://2paths.com" class="autohyperlink" target="_blank">2paths.com</a>).</p>]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/16/holidays-trying-to-make-an-impact-and-creative-capitalism/feed/</wfw:commentRss>
		</item>
		<item>
		<title>2008 Retrospective - Our Year Remembered</title>
		<link>http://www.2paths.com/2008/12/12/2008-retrospective-our-year-remembered/</link>
		<comments>http://www.2paths.com/2008/12/12/2008-retrospective-our-year-remembered/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 23:13:50 +0000</pubDate>
		<dc:creator>Judi</dc:creator>
		
		<category><![CDATA[Blog]]></category>

		<category><![CDATA[osx]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=362</guid>
		<description><![CDATA[This year we made a point of making time to reflect on things, not just at the end of the year, but all the way through it.  At the End of a project, the End of a quarter, sometimes even the end of a conversation.  We adopted a new routine of hosting Clearinghouse meetings to [...]]]></description>
			<content:encoded><![CDATA[<p>This year we made a point of making time to reflect on things, not just at the end of the year, but all the way through it.  At the End of a project, the End of a quarter, sometimes even the end of a conversation.  We adopted a new routine of hosting Clearinghouse meetings to reflect on how we are functioning on a team.  And we continued validating our past efforts and identifying new goals through our quarterly meetings, governed by the Rockefeller Habits.  We dedicated ourselves to project retrospectives, rather than calling them post-mortems.  Always the goal being to improve.   So naturally, the year would not be complete with a 2008 retrospective.  To reflect on what can be improved, and more importantly, to celebrate our successes and blessings!</p>
<p>We experienced what could best be described as an illuminating and transformational year at 2Paths.   From changes to our processes and tools to the diversification of our team demographic, to teaming up with some fabulous new valued partners and clients, change abounded.  And there’s not a soul among us who would argue that it wasn’t for the better.  As our year concludes, my 2008 retrospective blog finds no shortage of things to reminisce about.   Sit back and enjoy.</p>
<p>From a people perspective, the team welcomed 2 new babies into our extended family.  Congratulations to Michal and Lori on the birth of baby Cohen, and congratulations to Ricky and Lin on their second addition to the family, Lucas.  I personally bought a house and got married to the love of my life, Willy the caveman, in a small Whistler wedding. Garret married the love of his life, the beautiful Priscille, in grand fashion Winnipeg-style.  2Paths gladly welcomed new members to the team Omar Khan, Sandra Widjaja, Gary Meehan, Tim Oxenford, and. Kari Braaten.  And last, and very important - we celebrated Michal Urbanski’s 5-year anniversary with the company by sending him on kite-board lessons in Squamish.  He returned exhilarted and intact, thank goodness.</p>
<p>Processes and tools were areas that 2Paths focused heavily on in 2008, recognizing that these will differentiate us from our competition in the future.  We honed in on our existing skills by cultivating 3 certified scrum-masters (Lorill, Geoff and Omar).   Scrum (a brief daily morning developer meeting) has been pivotal to our successful software projects.   Someone likened it to inviting your mother-in-law to live with you – she may not fix everything, but she will most certainly point our everything that needs to be fixed.  Then it’s just about the fixing.    Next, the team continued to examine open source software tools and added some more to our repertoire, including Grails, Hudson, and Groovy, to name a few.   To ensure we got the latest on emerging technologies and uses of technologies, we also sent 2Pathsians to attend conferences on Geo-spatial technology, the Semantic Web, QCon (a conference of technical depth and enterprise focus), No Fluff Just Stuff, and Agile Methodologies.</p>
<p>In the spring, we moved our office to the Arthur Erikson Waterfall building by Granville Island from Gastown.   In addition to loving the view, we have been enjoying lunch at Go Fish, the NoodleBox, and Sushi Go, not to mention whipping up concoctions in our gourmet kitchen.  After our first pay cheque in the new location, our Synesso Cyncra coffee machine made its proud appearance in our kitchen providing java nirvana for everyone to enjoy.  There has been talk of a group membership to Caffeine Anonymous, but so far we’ve been holding out alright.</p>
<p>From a team-building perspective, we did a TON of fun things together this year.  Our long-standing tradition of playing together, letting off some steam, and laughing is our real secret to strong teamwork.  Here’s the illustrious list of our 2008 fun:</p>
<p>-    We bonded over some spring-skiing/riding at Grouse mountain, followed by beer on the patio in the glorious sun;<br />
-    We learned to Curl at Marpole Curling;<br />
-    We tested our trust in each other during rock-climbing;<br />
-    We golfed at Gleneagles and BBQed at Judi’s new home;<br />
-    We enjoyed some fine-dining at Chambar;<br />
-    We participated in Bike to Work week<br />
-    We enlisted a yoga instructor to lead us through weekly hatha yoga practices on the new roof-top patio in the summer, and in our boardroom in the winter.</p>
<p>One of our major projects has been with the &#8220;Insert name of international organization which we will shortly be revealing&#8221; on an application that has global impact and countless social good benefits.  It gave us an opportunity to go globetrotting to the likes of Paris and London.  Better yet, it presented a chance to work in concert with partners, Gagan Diesh and Kaaren Schulz of DesignStamp, <a title="DesignStamp" href="http://www.designstamp.com/" target="_blank">http://www.designstamp.com/,</a>whom we’ve grown to love and cannot do without.  We were also glad to continue our solid working relationship with our valued client, Carlson Wagonlit Travel, <a class="wp-caption-dd" title="CWT" href="http://www.carlsonwagonlit.com/en" target="_blank">http://www.carlsonwagonlit.com/en</a>.  And, we played pretend, and acted like a client to ourselves, dictating our own requirements towards an internal initiative which we will may be talking about a lot more in 2009.</p>
<p>So, as you can see we have been very busy this year.  Not just building web applications that make complicated problems palatable and bite-size, but also in being good to ourselves and to each other.   And we look forward to an exciting 2009, filled with market improvements, more work with our valued partners and clients, and at the very least, some good conversations, hopefully with you, over a fancy-pants coffee from our cool espresso machine.  Have a safe and happy holiday season, everyone!</p>
<div id="attachment_374" class="wp-caption alignnone" style="width: 486px"><a href="http://www.2paths.com/wp-content/uploads/2008/12/2paths_curling_2008_low.jpg"><img class="size-medium wp-image-374" title="2paths_curling_2008_low" src="http://www.2paths.com/wp-content/uploads/2008/12/2paths_curling_2008_low.jpg" alt="2Paths Team" width="476" height="317" /></a><p class="wp-caption-text">2Paths Team</p></div>]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/12/2008-retrospective-our-year-remembered/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Tequila Rendering Made Easier</title>
		<link>http://www.2paths.com/2008/12/12/tequila-rendering-made-easier/</link>
		<comments>http://www.2paths.com/2008/12/12/tequila-rendering-made-easier/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 20:01:52 +0000</pubDate>
		<dc:creator>Garrett</dc:creator>
		
		<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=322</guid>
		<description><![CDATA[Recently I&#8217;ve been working on our in-house open source project, Tequila. It is a RESTful web service framework, and was lacking some familiar rendering capabilities out of the box. (See tequilaframework.org/ for project details). The formats that we thought may be useful were XML, JSON, and RDF, and so I set out to provide these [...]]]></description>
			<content:encoded><![CDATA[<p><strong>R</strong>ecently I&#8217;ve been working on our in-house open source project, Tequila. It is a RESTful web service framework, and was lacking some familiar rendering capabilities out of the box. (See <a href="http://tequilaframework.org/" title="http://tequilaframework.org/" class="autohyperlink" target="_blank">tequilaframework.org/</a> for project details). The formats that we thought may be useful were <a href="http://en.wikipedia.org/wiki/Xml" target="_blank">XML</a>, <a href="http://en.wikipedia.org/wiki/Json" target="_blank">JSON</a>, and <a href="http://en.wikipedia.org/wiki/Resource_Description_Framework" target="_blank">RDF</a>, and so I set out to provide these basic abilities.</p>
<p><strong>O</strong>ur XML and JSON rendering functionality leverages the <a href="http://xstream.codehaus.org" target="_blank">XStream project</a>, and provides an easy mechanism for pairing aliases and their respective Java objects.<br />
The <a href="http://www.springframework.org/" target="_blank">Spring Framework</a> configuration in the webapp project sets the rendering information for each response type. Response types are used when specifying <em>routes</em>, which are the Tequila representation for URL request patterns.</p>
<p><strong>JSON example:</strong></p>
<pre class="syntax-highlight:xml">
&lt;bean id=&quot;dataPointJsonRenderer&quot; class=&quot;org.tequilaframework.core.renderer.JsonRenderer&quot;&gt;
&lt;property name=&quot;responseType&quot; value=&quot;datapoint/json&quot;/&gt;
&lt;property name=&quot;contentType&quot; value=&quot;text/plain&quot;/&gt;
&lt;property name=&quot;aliases&quot;&gt;
&lt;map value-type=&quot;java.lang.Class&quot;&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;dataPoints&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;java.util.List&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;dataPoint&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.DataPoint&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;time&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.TimeDimension&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;spatial&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.SpatialDimension&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;!-- Example omission --&gt;
&lt;!-- to omit a field, you must declare the parent class as the class value, and the key is the would-be rendered value --&gt;
&lt;!-- &lt;property name=&quot;omissions&quot;&gt;
&lt;map value-type=&quot;java.lang.Class&quot;&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;spatial&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.DataPoint&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
--&gt;
&lt;/bean&gt;
</pre>
<p><strong>XML example:</strong></p>
<pre class="syntax-highlight:xml">
&lt;bean id=&quot;dataPointXmlRenderer&quot; class=&quot;org.tequilaframework.core.renderer.XmlRenderer&quot;&gt;
&lt;property name=&quot;responseType&quot; value=&quot;datapoint/xml&quot;/&gt;
&lt;property name=&quot;contentType&quot; value=&quot;text/plain&quot;/&gt;
&lt;property name=&quot;aliases&quot;&gt;
&lt;map value-type=&quot;java.lang.Class&quot;&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;dataPoints&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;java.util.List&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;dataPoint&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.DataPoint&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;time&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.TimeDimension&lt;/value&gt;
&lt;/entry&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;spatial&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.SpatialDimension&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;!-- Example omission --&gt;
&lt;!-- to omit a field, you must declare the parent class as the class value, and the key is the would-be rendered value --&gt;
&lt;!-- &lt;property name=&quot;omissions&quot;&gt;
&lt;map value-type=&quot;java.lang.Class&quot;&gt;
&lt;entry&gt;
&lt;key&gt;&lt;value&gt;spatial&lt;/value&gt;&lt;/key&gt;
&lt;value&gt;com.twopaths.example.domain.DataPoint&lt;/value&gt;
&lt;/entry&gt;
&lt;/map&gt;
&lt;/property&gt;
--&gt;
&lt;/bean&gt;
</pre>
<p><strong>T</strong>he RDF renderer leverages the <a href="http://jena.sourceforge.net" target="_blank">Jena project</a> and <a href="http://code.google.com/p/jenabean/" target="_blank">Jenabean project</a>. Jena supported RDF formats include<em> RDF/XML, RDF/XML-ABBREV, N-TRIPLE, TURTLE, N3, N3-PP, N3-PLAIN, and N3-TRIPLE</em>. Because of Jena, the Tequila RDF renderer gets these formats for free. The only trick with RDF in Tequila is that you will need to use annotations in the Java classes you wish to have RDF support in. If you&#8217;re using <a href="http://www.hibernate.org/" target="_blank">Hibernate</a>, then you&#8217;ll likely already have RDF rendering configured. If no rdfType is specified, the default is RDF/XML.</p>
<p><strong>RDF example:</strong></p>
<pre class="syntax-highlight:xml">
&lt;bean id=&quot;dataDescriptionRdfRenderer&quot; class=&quot;org.tequilaframework.core.renderer.RdfRenderer&quot;&gt;
&lt;property name=&quot;responseType&quot; value=&quot;application/rdf&quot;/&gt;
&lt;property name=&quot;contentType&quot; value=&quot;text/plain&quot;/&gt;
&lt;property name=&quot;domain&quot; value=&quot;http://www.2paths.com/example&quot;/&gt;
&lt;property name=&quot;rdfType&quot; value=&quot;TURTLE&quot;/&gt;
&lt;/bean&gt;
</pre>
<p><strong>W</strong>ith multiple rendering capabilities, the GET request to the webapp can alter the rendering output by including the <em>flavor</em> RPC verb descriptor to modify the return format. For example, the URL of</p>
<p>http://localhost:8080/example/app/data/example?flavor=application/rdf</p>
<p>would return an RDF rendered output, and the original response format may have been JSON, or another response format laid out in the configuration file.</p>]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/12/12/tequila-rendering-made-easier/feed/</wfw:commentRss>
		</item>
		<item>
		<title>QCon SF 2008 - Technology Of Interest</title>
		<link>http://www.2paths.com/2008/11/26/qcon-sf-2008-technology-of-interest/</link>
		<comments>http://www.2paths.com/2008/11/26/qcon-sf-2008-technology-of-interest/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 19:33:24 +0000</pubDate>
		<dc:creator>Omar</dc:creator>
		
		<category><![CDATA[conference]]></category>

		<category><![CDATA[tech]]></category>

		<category><![CDATA[couchdb]]></category>

		<category><![CDATA[drizzle]]></category>

		<category><![CDATA[gearman]]></category>

		<category><![CDATA[memcached]]></category>

		<category><![CDATA[memcachedb]]></category>

		<category><![CDATA[mogilefs]]></category>

		<category><![CDATA[qconsf08]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=299</guid>
		<description><![CDATA[Part of the purpose of attending QCon was to get in synch with the tech community in regards to technology they have experimented with and have found use for. The following is a list of technology/frameworks/etc of interest that I took away from the conference:

CouchDB - Document oriented database

Memcached - Distributed Hashmap
MemcacheDB - A database [...]]]></description>
			<content:encoded><![CDATA[<p>Part of the purpose of attending QCon was to get in synch with the tech community in regards to technology they have experimented with and have found use for. The following is a list of technology/frameworks/etc of interest that I took away from the conference:</p>
<ul>
<li><a href="http://incubator.apache.org/couchdb/">CouchDB</a> - Document oriented database<a href="http://incubator.apache.org/couchdb/"><br />
</a></li>
<li><a href="http://www.danga.com/memcached/">Memcached</a> - Distributed Hashmap</li>
<li><a href="http://memcachedb.org/">MemcacheDB</a> - A database built as on Memcached and BerkleyDB<a href="http://memcachedb.org/"><br />
</a></li>
<li><a href="https://launchpad.net/drizzle">Drizzle</a> - Lightweight SQL Database for the cloud/web<a href="https://launchpad.net/drizzle"></a></li>
<li><a href="http://www.danga.com/gearman/">GearMan</a> - Distributed processing framework<a href="http://www.danga.com/gearman/"><br />
</a></li>
<li><a href="http://www.danga.com/mogilefs/">MogileFS</a> - Distributed file system<a href="http://www.danga.com/mogilefs/"><br />
</a></li>
</ul>
<p>I intend to spend some time investigating each of these pieces of technology in the coming months with the hope of making use of them when and where applicable.</p>]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/11/26/qcon-sf-2008-technology-of-interest/feed/</wfw:commentRss>
		</item>
		<item>
		<title>QCon SF 2008 - Day 3</title>
		<link>http://www.2paths.com/2008/11/24/qcon-sf-2008-day-3/</link>
		<comments>http://www.2paths.com/2008/11/24/qcon-sf-2008-day-3/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 22:08:47 +0000</pubDate>
		<dc:creator>Omar</dc:creator>
		
		<category><![CDATA[conference]]></category>

		<category><![CDATA[2008]]></category>

		<category><![CDATA[conclusion]]></category>

		<category><![CDATA[couchdb]]></category>

		<category><![CDATA[day 3]]></category>

		<category><![CDATA[digg]]></category>

		<category><![CDATA[facebook]]></category>

		<category><![CDATA[qcon sf]]></category>

		<category><![CDATA[san francisco]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=289</guid>
		<description><![CDATA[I was pretty excited about the &#8220;Architectures you&#8217;ve always wondered about&#8221; stream for day 3 of the conference. It started off horribly. Dan Pritchett of MySpace was up first and basically took the change to showoff his personally little project that allows events from their thousands of servers to notify them what&#8217;s going on within [...]]]></description>
			<content:encoded><![CDATA[<p>I was pretty excited about the &#8220;Architectures you&#8217;ve always wondered about&#8221; stream for day 3 of the conference. It started off horribly. Dan Pritchett of MySpace was up first and basically took the change to showoff his personally little project that allows events from their thousands of servers to notify them what&#8217;s going on within them in a centralized manner. How he figured people were interested in hearing about the log files of <a href="http://MySpace.com" title="http://MySpace.com" class="autohyperlink" target="_blank">MySpace.com</a> baffles me&#8230;not only were people rolling their eyes but some were falling asleep (myself included). He really didn&#8217;t do anything to help the tech community have a better view of MySpace. He finished his session in 25 minutes and then opened the floor for questions&#8230;crickets for the most part. The moderator tried valiantly to get people to ask questions but what the hell do you want us to ask about log files? There went 30 minutes of my life I will never get back.</p>
<p>Joe Stump from <a href="http://Digg.com" title="http://Digg.com" class="autohyperlink" target="_blank">Digg.com</a> was up next and his session was awesome. He talked about the evolution of their architecture from the point he joined to what they are planning on rolling out early next year along with some of the bumps they&#8217;ve encountered. MySQL&#8217;s scalability had major issue so they moved to IDDB and are considering using MemcacheDB which is MemcacheD mixed with Berkley DB.  Joe pointed out their use of <a href="http://www.danga.com/mogilefs/" target="_blank">MogileFS</a> for the management of images on <a href="http://digg.com/images" target="_blank">digg images</a> which I will be taking a look at for our current project. Joe, you rock, maybe you can give some pointers to Dan&#8230;then again hopefully MySpace will send somone with a clue next year.</p>
<p>Aditya Agarwal from facebook was great. He talked about all the different aspects of facebook and the use of PHP/MySQL being the underlying architecture and how for them it . They tend to use MySQL simply as a key value store and profile content is randomly scattered across their thousands of servers. They use LAMP for the most part but have created a framework that allows them to use services written in other languages within their application.</p>
<p>The discovery of the day was <a href="http://incubator.apache.org/couchdb/" target="_blank">CouchDB</a>. One of the lead developers/designers was sitting at the same table as me during the Digg session. Tim Bray was quite excited about the technology as well having mentioned it in his keynote on day 2. I attended one of two sessions about that covered what it&#8217;s about from a high level. It has it&#8217;s roots in Lotus Notes database design given that it was created by one of the people who worked on Lotus Notes in the past. It has some very cool features:</p>
<ul>
<li>RESTful so it doesn&#8217;t require any connectors</li>
<li>Stores all content in JSON</li>
<li>Querying the database is done via javascript functions for performing map reduce like functionality</li>
<li>Very efficient and performs versioning and synchronization when distributed</li>
</ul>
<p>Jan made some good arguments was to why it has some strengths that traditional RDB&#8217;s don&#8217;t such as no need for schema management, etc. It&#8217;s a technology that I plan on taking a serious look at and may possibly use in the future.</p>
<p>In conclusion, QCon was a great experience. The hosts tried their best to make sure things were as tech focused as possible. There is a need to ensure that speakers cater their presentations to the audience and keep to the subject of the presentation. The lagging economy did have an effect on the conference, there were 200+ people that had been registered that didn&#8217;t attend (you could see all of the uncollected badges at the registration desk) and if the economy improves I think that next year will be even better. It&#8217;s truly a conference for developers by developers which I truly enjoyed. It was great to meet several of the authors of my favourite tech books. I would have preferred more opportunities to network with the people at the conference, an overall guest list would have helped with that or a formal networking event given that a large percentage of the nerds there were stereotypical introverted nerds who didn&#8217;t like having a strange person walk up to them and make conversation. Maybe I came off as sleazy or creepy or a threat to homeland security ;). Regardless, I hope to attend next year.</p>
<p><strong>Update:</strong> This blog post has been <a title="QConSF 2008 Summary" href="http://www.infoq.com/articles/qconsf-2008-summary" target="_blank">featured on the <a href="http://infoq.com" title="http://infoq.com" class="autohyperlink" target="_blank">infoq.com</a> website</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/11/24/qcon-sf-2008-day-3/feed/</wfw:commentRss>
		</item>
		<item>
		<title>QCon SF 2008 - Day 2</title>
		<link>http://www.2paths.com/2008/11/20/qcon-sf-2008-day-2/</link>
		<comments>http://www.2paths.com/2008/11/20/qcon-sf-2008-day-2/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 06:17:16 +0000</pubDate>
		<dc:creator>Omar</dc:creator>
		
		<category><![CDATA[conference]]></category>

		<category><![CDATA[Bob Lee]]></category>

		<category><![CDATA[concurrency]]></category>

		<category><![CDATA[open-source]]></category>

		<category><![CDATA[QCon SF 2008]]></category>

		<category><![CDATA[Rod Johnson]]></category>

		<category><![CDATA[scalability]]></category>

		<category><![CDATA[Tim Bray]]></category>

		<guid isPermaLink="false">http://www.2paths.com/?p=270</guid>
		<description><![CDATA[As I mentioned in my post yesterday, I was expecting more from the conference today than I experienced yesterday. What I&#8217;m expecting at a tech conference is to talk tech such that the speaker presents their expertise or lessons learned. I didn&#8217;t get much of that yesterday but today was another story. We kicked off [...]]]></description>
			<content:encoded><![CDATA[<p>As I mentioned in <a title="QCon SF 2008 - Day 1" href="http://www.2paths.com/2008/11/19/qcon-sf-2008-day-1/">my post yesterday</a>, I was expecting more from the conference today than I experienced yesterday. What I&#8217;m expecting at a tech conference is to talk tech such that the speaker presents their expertise or lessons learned. I didn&#8217;t get much of that yesterday but today was another story. We kicked off the day with a talk by Tim Bray about the database and data access and the evolution of the database and what one needs to keep in mind when designing a system that uses them. He introduced techniques such as the use of MemCacheD that are used by all the big name web apps as a distributed cache of data retrieved from the database. He talked about Drizzle that is a light-weight database that removes all the stuff that no-one ever uses in major databases that slow down the database server and lastly column oriented databases such as Googles BigTable. All in all he provided some great insight on tech in the database layer which warrant further investigation.</p>
<p>Next was a panel discussion on scalability and emphasized the need to understand the update requirements of the system you are designing. They proposed that there are two types of design:</p>
<ol>
<li>Design for scalability up front</li>
<li>Design for simplicity and deal with bottle-necks as they pop-up</li>
</ol>
<p>I&#8217;m not sure if I&#8217;d ever go with option #2 but they made a good point about how many architects design for things to be bullet proof when one really doesn&#8217;t really have the requirement for it to be bulletproof. I fully agree with that principle. There was mention of several websites such as flickr that have made some very good decisions on having that happy medium</p>
<p>The next talk was about the Java 7 concurrency library and the need for making things concurrent given the fact that processors are not getting faster but are moving towards multiple cores. Therefore, we as developers need to ensure that we ensure our applications are making everything run in parallel (concurrent). One might feel that if you are running a website that since every request is being handled by a different thread your job is complete. However, how many of us receive enough requests 24*7 to keep all the cores busy. Therefore, we need to make sure that applications is decomposed to the extent that we are doing everything concurrently that can be done concurrently to ensure maximum CPU utilization and decreased response time and therefore an improved user experience.</p>
<p>The last session of interest was a panel discussion on the affect that the open-source movement has and on java. It was the consensus that the open-source saved java from mediocrity and J2EE from certain death. The focus of the discussion moved to open-source during the current economic condition. The panel felt that slashed budgets within most companies would allow open-source to flourish, at least those that are well established. The last point of interest was about how they make a decision within their companies about what to open-source and what to charge for. Bob Lee of Google said that they open-source low level tools and frameworks and charge for things they build upon them. Others such as a guy from MuleSource and Rod Johnson from Spring Source said that they charge when people are already likely to be paying other vendors for their product/services. For example, the quote of the night was from Rod Johnson</p>
<blockquote><p>If you use MySql, tomcat and Apache as your application stack then you can use spring for free and that&#8217;s great. However, if you are using Oracle Rack for a database, BEA Weblogic for an app server then you have no right to complain when we charge you for a Spring to Oracle RACK connector.</p></blockquote>
<p>The point being if you&#8217;re already spending money then why shouldn&#8217;t we ask to be paid for what we are offering.</p>
<p>Tomorrow has another set of very interesting streams and discussions. I&#8217;m looking forward to the stream called &#8220;Architectures you&#8217;ve always wondered about.&#8221;</p>
<p><strong>Update:</strong> This blog post has been <a title="QConSF 2008 Summary" href="http://www.infoq.com/articles/qconsf-2008-summary" target="_blank">featured on the <a href="http://infoq.com" title="http://infoq.com" class="autohyperlink" target="_blank">infoq.com</a> website</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.2paths.com/2008/11/20/qcon-sf-2008-day-2/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
