<?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>Gridshore</title>
	<atom:link href="http://www.gridshore.nl/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gridshore.nl</link>
	<description>A weblog about software engineering, Architecture, Technology an other things we like.</description>
	<lastBuildDate>Fri, 23 Mar 2012 15:54:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Deployments with Git and Bash on a Mac</title>
		<link>http://www.gridshore.nl/2012/03/23/deployments-with-git-and-bash-on-a-mac/</link>
		<comments>http://www.gridshore.nl/2012/03/23/deployments-with-git-and-bash-on-a-mac/#comments</comments>
		<pubDate>Fri, 23 Mar 2012 15:52:33 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Mac OSX]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[macosx]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1229</guid>
		<description><![CDATA[<p>I am creating a number of websites based on wordpress. Up till now I was just hacking the server and hoping that a backup was in place. At a certain moment I accidentally broke the .htaccess file. I enabled nice permalinks for an image library and my .htaccess file got overwritten. I wanted to [...]]]></description>
			<content:encoded><![CDATA[<p>I am creating a number of websites based on wordpress. Up till now I was just hacking the server and hoping that a backup was in place. At a certain moment I accidentally broke the .htaccess file. I enabled nice permalinks for an image library and my .htaccess file got overwritten. I wanted to have a look at the backup to see the rewrite rules I had in place. The hosting party wanted me to pay around 40 euros to provide the backup. That made me think about my hacking around on the server. There should be a better option than this.</p>
<p>I started thinking about putting the sources in a version control system. Since I like Git and have a Github account I wanted to store the files in Git. But I had some other requirements.</p>
<ul>
<li>I do not want to manually copy the changed files to the server.</li>
<li>I am limited to ftp access, the hosted does not provide ssh access.</li>
<li>I want to be able to make quick changes from multiple laptops.</li>
<li>I want to have the changes taken from Git but also changes that have not yet been committed if I wanted to.</li>
<li>I have no requirements for removing files, this does not happen a lot.</li>
<p> </ul>
<p>Since I am on a Mac and have some very basic experience with Bash, I decided to use Bash. I did have some issues with FTP, but more on that later on.</p>
<p>If you are curious about the websites I have created:</p>
<p><a href="http://www.yvonnevandermey.nl/">Yvonne van der Mey ~ Wildlife Photographer</a><br/><br />
<a href="http://www.nicobulder.com/">Nico Bulder ~ Wildlife Painter</a><br/><span id="more-1229"></span><br />
<h2>Repository layout</h2>
<p>I want to support multiple sites in one repository. I give each site it&#8217;s own folder. The root of the project contains the deploy.lib file. This file contains the reusable code, which is almost everything. Each website folder contains a deploy.sh file. In the website folder we also have a file ftpconfig. This file is discussed later on when discussing the NcFtp client.</p>
<p>I do not store the complete wordpress installation in git. I most of store the template that you can find under wp-content/themes/yvonne. But I also add files that I added to the wordpress install like the favicon.ico. The idea is that I copy all changes over the existing wordpress installation. Like I stated before, I am not going to remove files. Using this mechanism I can also add custom plugins in the same way.</p>
<h2>Explaining Git commands</h2>
<p>The sources are stored in Git. This makes it easier to track changes and it helps me doing stuff the right way. So what is the right way? I want to deploy files that have changes in commits. Therefore I store the sha1 key of the last commit that I have deployed in a file. The next time I deploy changes, I read this file and deploy all changes after this commit. Sometimes however, you are debugging things and you do not want to continuously do commits. In that scenario you want to be able to deploy all changes in your local copy. This is also possible with the script.</p>
<h3>Changes based on commits</h3>
<p>Git has good support for finding more information on commits. There are multiple commands that can do the trick. For the most clean output came from the following command:</p>
<pre class="brush: bash; title: ; notranslate">
git show --pretty=&quot;format:&quot; --name-only $startingfrom..HEAD
</pre>
<p>The $startingfrom is the sha1 key obtained through a provided parameter or from the file that was written the last time we did a deploy.</p>
<h3>SHA1 of the last commit</h3>
<p>We want to keep track of the changes that have already been deployed to the server. Since we are basing our deploys git commits, we want to obtain the sha1 key of the last commit. Git provides are daily easy way to obtain this key.</p>
<pre class="brush: bash; title: ; notranslate">
git log -1 --pretty=format:%H &gt; $shaversion
</pre>
<p>With these commands we know enough to obtain changes after the last deploy. But what if we are trying something and want to make it possible to deploy files that have not yet been committed.</p>
<h3>Changes in the local workspace</h3>
<p>Changes that are not yet committed are called changes in the workspace of git. Again provides a good way to obtain the names of the files than have changes in the local workspace. You can check them against he HEAD.</p>
<pre class="brush: bash; title: ; notranslate">
git diff HEAD --name-only
</pre>
<p>That is it. Now we have the power to create a list of files that have changed. How can we copy files to the server using ftp.</p>
<h2>NcFtp</h2>
<p>The bash script creates a folder with a nested folder structure. The structure contains files on multiple levels. We want to use one command to recursively ftp all files to the server. Well, that is a hassle. First you have to overcome issue with ftp and logging in. Using the .netrc file this is easy to overcome on the mac. Still this does not resolve all our issues. Ftp does not support recursive ftp in a folder. You can use mput, but this only works for files in a folder. Not in a nested folder.</p>
<p>There are other options for ftp. I decided to use <a href="http://www.ncftp.com/ncftp/">ncftp client software</a>. Easy to install using Homebrew or Macports. I store the ftp connection data in a file that I configure in the ncftpput command. THe following command recursively copies the sources in the provided local folder to the provided remote folder.</p>
<p>The ftpconfig file must contain three properties: host, user, pass. The following command shows how you can copy the content of a directory to the server.</p>
<pre class="brush: bash; title: ; notranslate">
ncftpput -f ftpconfig -R mainwebsite_html deploy/yvonne/*
</pre>
<h2>Doing bash</h2>
<p>Time to put the pieces together. The glue is provided by bash. </p>
<h3>Site specific configuration</h3>
<p>Most of the bash code is shared between the different websites. That code is in the deploy.lib file. Of course you can place all code in one file. I have just one parameter and the included of the library file in the specific site deploy.sh file.</p>
<pre class="brush: bash; title: ; notranslate">
sitename=&quot;yvonne&quot;
. ../deploy.lib
exit 1
</pre>
<h3>Handling input</h3>
<p>You can provide a few options to the script to influence what it does. It is good practice to show the options in a usage or help method. The following code block shows this method as well as the handling of the provided arguments.</p>
<pre class="brush: bash; title: ; notranslate">
function usage() {
	echo &quot;Usage: `basename $0` [--nocommit] {GIT REVISION SHA}&quot;
	echo &quot;    optional flags: &quot;
	echo &quot;        --help, --usage # show this file&quot;
	echo &quot;        --nocommit #By default only commits are used, with this flag we use changes in your workspace.&quot;
	echo &quot;        --sha1 &lt;value&gt; #Uses the commits from the provided value to the HEAD. Default reads the sha1.txt file.&quot;
}

commitonly=true
while true; do
	# case $# in 0) usage; exit 2 ;; esac
	case $1 in
		--help)				usage; exit 1 ;; esac
	case $1 in
		--usage)			usage; exit 1 ;; esac
	case $1 in
		--nocommit)			shift; commitonly=false ;; esac
	case $1 in
		--sha1)				shift; startingfrom=$1; shift ;;
		*) break ;;
	esac
done
</pre>
<p>The default is to gather all changes since the last commit that got deployed using the sha1 key in the sha1.tx file. By providing the &#8211;nocommit flag you can tell the script to switch to gathering changes in the local workspace. By providing the argument &#8211;sha1, you can pass another sha1 key to obtain changes for.</p>
<h3>Obtaining the right changes</h3>
<p>To find the files that have changed, we create a file containing the path to a file that is changed per line. By looping through these lines we can copy all files that we want to deploy. The next code block creates this file, but it has two side effects. It also creates a version.php that contains the date of the deploy as well as all the files that have been deployed. The second site effect is creating the sha1.txt file that contains the sha1 key of the last commit that has been deployed.</p>
<pre class="brush: bash; title: ; notranslate">
filelist=&quot;files-$(date +&quot;%s&quot;).txt&quot;
mkdir -p &quot;deploy/$sitename&quot;
versionphp=&quot;deploy/$sitename/version.php&quot;
shaversion=&quot;sha1.txt&quot;

if $commitonly ; then
	if [[ ${#startingfrom} -lt 1 ]]; then
		echo &quot;Need to reed the sha1.txt file&quot;
		while read line; do
			startingfrom=$(echo $line);
		done &lt; $shaversion
	fi
	echo &quot;Using commits for changes: $startingfrom&quot;

	git show --pretty=&quot;format:&quot; --name-only $startingfrom..HEAD &gt; $filelist
	echo &quot;Committed changes: $(date)&quot; &gt; $versionphp
	echo &quot;&lt;br&gt;Last commit: $startingfrom&quot; &gt;&gt; $versionphp
	git log -1 --pretty=format:%H &gt; $shaversion
	echo &quot;&quot; &gt;&gt; $shaversion
else
	echo &quot;We only use changes in the workspace&quot;
	git diff HEAD --name-only &gt; $filelist
	echo &quot;Local changes: $(date)&quot; &gt; $versionphp
fi
</pre>
<p>Line 6 determines if the starting from parameter has been provided by an argument to the script. We determine if the length of the value is smaller than 1. If so we obtain it from the file sha1.txt. I think this was the hardest trick.</p>
<h3>Ftp the changed files</h3>
<p>Now we have a file that contains all the names of the files that have changed. The next block loops over the files and filters a few of them based on the website we are working for at the moment. If we have files left at the end we use the ncftpput command to actually ftp them.</p>
<pre class="brush: bash; title: ; notranslate">
ftpfiles=false
for file in $(&lt;$filelist); do
	if [[ $file == $sitename* &amp;&amp; $file != $sitename/deploy* &amp;&amp; $file != $sitename/sha1.txt ]]; then
		echo &quot;$file&quot;
		echo &quot;&lt;br&gt;$file&quot; &gt;&gt; $versionphp
		mkdir -p &quot;deploy/$(dirname $file)&quot;
		cp &quot;../$file&quot; &quot;deploy/$file&quot;
		ftpfiles=true
	fi
done

if $ftpfiles ; then
	ncftpput -f ftpconfig -R mainwebsite_html deploy/yvonne/*
else
	echo &quot;Nothing to ftp.&quot;
fi
</pre>
<h2>Concluding</h2>
<p>I am now able to adjust my workflow. I can make the changed locally, commit them into git before I actually automatically deploy them to the server. It is nice to see what you can do with a little bit of bash. If you have improvements please let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2012/03/23/deployments-with-git-and-bash-on-a-mac/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A MongoDB based Axon framework event store</title>
		<link>http://www.gridshore.nl/2012/02/28/a-mongodb-based-axon-framework-event-store/</link>
		<comments>http://www.gridshore.nl/2012/02/28/a-mongodb-based-axon-framework-event-store/#comments</comments>
		<pubDate>Tue, 28 Feb 2012 08:15:56 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Axon Framework]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[mongodb]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1225</guid>
		<description><![CDATA[<p>For a while we are working on the Axon framework. One of the main components of Axon is the event store. Axon framework has a JPA based event store as well as a file based event store. Within the incubator we have also been working on the MongoDB based event store. In this blog [...]]]></description>
			<content:encoded><![CDATA[<p>For a while we are working on the <a href="http://www.axonframework.org">Axon framework</a>. One of the main components of Axon is the event store. Axon framework has a JPA based event store as well as a file based event store. Within the incubator we have also been working on the MongoDB based event store. In this blog post I am going to explain the internals of the MongoDB event store. I will also discuss some of the next steps we want to take with the mongo event store.</p>
<p><span id="more-1225"></span><br />
<h2>Incubator Status</h2>
<p>The mongo event store is becoming fully functional right now. At the moment the event store is functional for the 1.3.x branch of axon. We have a working example &#8220;The Axon Trader&#8221; using the event store. We do not have it running in a project in production yet. If you are considering to do use it in production please let us know about your findings.</p>
<p>The planning is to drop the incubator status starting Axon 2.0. Using the mentioned sample we are going to do some stress testing and we are thinking about improvements. More on these in the Next steps section.</p>
<h2>Connecting to Mongo</h2>
<h3>MongoFactory</h3>
<p>Mongo can be used as a single instance, which is not really suitable for a production environment. A better setup is to use a replication set of mongo instances. Using the MongoFactory this can be hidden for the other parts of the application.</p>
<p>The factory takes a list of server addresses, you can override the MongoOptions as well as the WriteConcern. Of course we take good defaults. There is an option to set the mode to single instance or multiple instance using a system property: <em>axon.mongo.singleinstance</em>. This system property takes precedence over other settings.</p>
<p>In the end, the MongoFactory is used to create a Mongo instance. This instance should be provided to the implementation of the MongoCollections class. More on this later on.</p>
<h3>MongoOptionsFactory</h3>
<p>The configuration of Mongo using the java driver is executed using the MongoOptions class. This factory is used to create such an object using defaults but with the possibility to provider other values for the most important properties. Some of the options you can configure are: number of connections per host, the connection time-out and auto-connect retry.</p>
<h3>The collections in Mongo</h3>
<p>Mongo uses collections to store data. The names of these collections that Axon uses for the event store as well as the saga store can be configured. Of course logical default values are provided as well. If you want to use other collections you can provide your own implementation of this interface or provide other names to the default implementation of the interface.</p>
<h2>Overview of the classes</h2>
<p>The following image gives you an overview of the important classes.</p>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://blog.dutchworks.nl/wp-content/uploads/2012/02/axon-mongo-eventstore.png" alt="Axon mongo eventstore" border="0" width="600" height="436" /></p>
<h2>Event repository</h2>
<p>The event repository, MongoEventStore, is responsible for storing and retrieving the events. Just like the other implementations of the event stores, you can provide your own event serializer. By default XStream is used to serialize the events.</p>
<p>The java driver for mongo makes it easy to store new documents in Mongo and query the existing documents. By using the EventStoreCollections object we obtain a reference to the actual collection and by calling insert we add new documents to the collection. To get an idea about the code, have a look at the following function of the event store.</p>
<pre class="brush: java; title: ; notranslate">
public void appendEvents(String type, DomainEventStream events) {
    List&lt;DBObject&gt; entries = new ArrayList&lt;DBObject&gt;();
    while (events.hasNext()) {
        DomainEvent event = events.next();
        EventEntry entry = new EventEntry(type, event, eventSerializer);
        entries.add(entry.asDBObject());
    }
    eventStoreCollections.domainEventCollection().insert(entries.toArray(new DBObject[entries.size()]));
}
</pre>
<p>A similar method is available to store snapshot events.</p>
<p>It becomes interesting when reading events to recreate an aggregate. Before reading events that need to be applied, we first need to find the latest snapshot. The following code block gives an idea about finding the latest snapshot event.</p>
<pre class="brush: java; title: ; notranslate">
private EventEntry loadLastSnapshotEvent(String type, AggregateIdentifier identifier) {
    DBObject mongoEntry = BasicDBObjectBuilder.start()
            .add(EventEntry.AGGREGATE_IDENTIFIER_PROPERTY, identifier.asString())
            .add(EventEntry.AGGREGATE_TYPE_PROPERTY, type)
            .get();
    DBCursor dbCursor = eventStoreCollections.snapshotEventCollection()
            .find(mongoEntry)
            .sort(new BasicDBObject(EventEntry.SEQUENCE_NUMBER_PROPERTY, -1))
            .limit(1);

    if (!dbCursor.hasNext()) {
        return null;
    }
    DBObject first = dbCursor.next();

    return new EventEntry(first);
}
</pre>
<p>Now you have seen the main features of the event store in Mongo. The next step is to store and load Saga instances.</p>
<h2>Saga repository</h2>
<p>The mongo part for Saga&#8217;s is even easier than the events. We do not have to account for snapshots, which makes it easier. Just use the identifier of a saga instance to store, load and delete a document. The repository supports storing the associations between Saga&#8217;s as required by Axon. It also supports the ResourceInjector if your saga needs other resources to do it&#8217;s job. Think about the command bus to send new commands.</p>
<p>The structure is the same as for the event store implementation. The SagaStoreCollections provides access to the collections in the mongo database as well as the database itself.</p>
<h2>Next steps</h2>
<p>We are constantly looking for improvements in the mongo implementation. Allard is working on a specific Mongo serializer. That way we are nog serializing to XML and storing that xml. We will store the content in a DBObject and that way in a basic mongo document structure. More on this will follow later on in another blog post.</p>
<p>As mentioned we are planning on doing some performance tests and experiment with indexes to improve performance.</p>
<p>I you have improvements, bugs or ideas feel free to file an issue on our Github project.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2012/02/28/a-mongodb-based-axon-framework-event-store/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Creating an rss feed using the latest features of Hippo</title>
		<link>http://www.gridshore.nl/2011/12/13/creating-an-rss-feed-using-the-latest-features-of-hippo/</link>
		<comments>http://www.gridshore.nl/2011/12/13/creating-an-rss-feed-using-the-latest-features-of-hippo/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 15:36:57 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[server technology]]></category>
		<category><![CDATA[hippo]]></category>
		<category><![CDATA[rome]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1216</guid>
		<description><![CDATA[<p>On my employers blog I wrote a piece about a new feature of Hippo called pipelines that can be used to create new content channels. We have created an rss feed using the standard components of Hippo combined with the Rome project. If you are interested you can read the blog post here:</p> <p>http://blog.dutchworks.nl/2011/12/13/embedding-rss-in-hippo-using-the-pipelines-feature/</p> ]]></description>
			<content:encoded><![CDATA[<p>On my employers blog I wrote a piece about a new feature of Hippo called pipelines that can be used to create new content channels. We have created an rss feed using the standard components of Hippo combined with the Rome project. If you are interested you can read the blog post here:</p>
<p><a href="http://blog.dutchworks.nl/2011/12/13/embedding-rss-in-hippo-using-the-pipelines-feature/">http://blog.dutchworks.nl/2011/12/13/embedding-rss-in-hippo-using-the-pipelines-feature/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/12/13/creating-an-rss-feed-using-the-latest-features-of-hippo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Leaving JTeam joining Dutchworks</title>
		<link>http://www.gridshore.nl/2011/10/11/leaving-jteam-joining-dutchworks/</link>
		<comments>http://www.gridshore.nl/2011/10/11/leaving-jteam-joining-dutchworks/#comments</comments>
		<pubDate>Tue, 11 Oct 2011 19:48:20 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[dutchworks]]></category>
		<category><![CDATA[JTeam]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1206</guid>
		<description><![CDATA[<p>In this post I want to share something that just happened to me this week. On monday I started as usual for the past three years or so. At the end of the day I left JTeam behind and started working for Dutchworks. Ok, I am trying to be funny. It most probably is [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.gridshore.nl/wp-content/uploads/dutchworks_logo.jpg" alt="Dutchworks logo" title="dutchworks_logo" width="300" height="44" style="float:left"/>In this post I want to share something that just happened to me this week. On monday I started as usual for the past three years or so. At the end of the day I left JTeam behind and started working for Dutchworks. Ok, I am trying to be funny. It most probably is not working. Or are you smiling?</p>
<p>Enough of the fun part, now seriously. JTeam has outgrown it&#8217;s name. The past year a lot has changed and a new name is the next logical step. I cannot explain this better than my CEO Steven Schuurman. If you are interested you can read his announcement here:</p>
<p><a href="http://blog.dutchworks.nl/2011/10/10/hot-off-the-press-as-of-today-“jteam”-will-be-known-as-“dutchworks”/">http://blog.dutchworks.nl/2011/10/10/hot-off-the-press-as-of-today-“jteam”-will-be-known-as-“dutchworks”/</a></p>
<p>Head over to our new website: <a href="http://www.dutchworks.nl">http://www.dutchworks.nl</a>. Help us spread the word.</p>
<p>Hope to see you back when we write our next technical blog.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/10/11/leaving-jteam-joining-dutchworks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cleaning up artifactory with a groovy script</title>
		<link>http://www.gridshore.nl/2011/10/03/cleaning-up-artifactory-with-a-groovy-script/</link>
		<comments>http://www.gridshore.nl/2011/10/03/cleaning-up-artifactory-with-a-groovy-script/#comments</comments>
		<pubDate>Mon, 03 Oct 2011 09:10:45 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[groovy and grails]]></category>
		<category><![CDATA[artifactory]]></category>
		<category><![CDATA[cleaning]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1192</guid>
		<description><![CDATA[<p>On my employers blog I wrote an article about cleaning up your local maven repository. It gets polluted with old snapshot artifacts easily. It also leaves a lot of build around if you release regularly. After cleaning up your local copy you start thinking about the repository on the server. Would that also become [...]]]></description>
			<content:encoded><![CDATA[<p>On my employers blog I wrote an article about cleaning up your local maven repository. It gets polluted with old snapshot artifacts easily. It also leaves a lot of build around if you release regularly. After cleaning up your local copy you start thinking about the repository on the server. Would that also become as big as your local one? Of course. Therefore we need to clean that one up as well.</p>
<p>In most of our projects we use <a href="http://www.jfrog.com/">Artifactory</a>. It is nice that artifactory comes with a REST based api. The url&#8217;s can be a bit better and the content type of the response is not what I would expect. Still the documentation is good and lost of actions are possible. In this blog post I show you the basics of interacting with the REST api using groovy. Now let us shrink the repo.</p>
<p><span id="more-1192"></span><br />
<h2>Introducing the artifactory api</h2>
<p>The frog wiki has a wiki page dedicated to the api. This page shows the GET/DELETE/PUT requests that you can execute. It shows the url, the response and the content type. If you click the following link you jump to the definition of Folder Info. After the link an image with the same data at the time of writing.</p>
<p><a href="http://wiki.jfrog.org/confluence/display/RTF/Artifactory%27s+REST+API#Artifactory%27sRESTAPI-FolderInfo">http://wiki.jfrog.org/confluence/display/RTF/Artifactory%27s+REST+API#Artifactory%27sRESTAPI-FolderInfo</a><br/><br />
<img style="display:block; margin-left:auto; margin-right:auto;" src="http://www.gridshore.nl/wp-content/uploads/Screen-Shot-2011-09-26-at-16.08.39.png" alt="Screen Shot 2011 09 26 at 16 08 39" border="0" width="600" height="442" /></p>
<p>In the image you can also see the JSON response for the specific request. Have a look at the structure of the response. Look at the children. We will use it later on.</p>
<h2>Obtaining folder info</h2>
<p>Time to show some code. We will first have a look at a function to obtain information about the folder as provided by the caller. Since we group the functions in a class we have to look at configuration of this class as well. The constructor accepts a map that we call config. That way you can provided configuration for the server, the repository and the versions to remove. An example of the config map is.</p>
<pre class="brush: groovy; title: ; notranslate">
def config = [
    server: 'http://localhost:8080',
    repository: 'libs-release-local',
    versionsToRemove: ['/3.2.0-build-'],
    dryRun: false]
</pre>
<p>Than we can ask for information about a folder. The following code block shows two functions, one to obtain information about a folder and the other to ask for a connection with the server.</p>
<pre class="brush: groovy; title: ; notranslate">
def JSON folderInfo(path) {
    def binding = [repository: config.repository, path: path]
    def template = engine.createTemplate('''/artifactory/api/storage/$repository/$path''').make(binding)
    def query = template.toString()

    def server = obtainServerConnection()
    def resp = server.get(path: query)
    if (resp.status != 200) {
        println &quot;ERROR: problem obtaining folder info: &quot; + resp.status
        println query
        System.exit(-1)
    }
    return resp.data
}

private RESTClient obtainServerConnection() {
    def server = new RESTClient(config.server)
    server.parser.'application/vnd.org.jfrog.artifactory.storage.FolderInfo+json' = server.parser.'application/json'
    server.parser.'application/vnd.org.jfrog.artifactory.repositories.RepositoryDetailsList+json' = server.parser.'application/json'

    return server
}
</pre>
<p>We make use of the groovy <a href="http://groovy.codehaus.org/api/groovy/text/SimpleTemplateEngine.html">SimpleTemplateEngine</a>. As you can see we build the query string with placeholders and attach a map with parameters to the template engine. Next step is to generate the query. After obtaining the connection to the server we execute the GET request and obtain the JSON data from the response. Notice the lines in the obtainServerConnection. The last two lines add mappings for the artifactory provided content types. We want them to be treated as normal json responses or else our mapping framework (Jackson) will not be able to process the result.</p>
<h2>Removing items</h2>
<p>The goal for this blog post is to present a script to clean your artifactory repository. Now that we know how to obtain information about a folder in artifactory, it is time to have a look at cleaning. The idea is to take the provided path as a starting point. Go through all the folders recursively and check if we are in an artifact folder. An artifact folder contains artifacts and should not have other folders. If a folder is not an artifact folder we are dealing with a grouped (maven terms). In our case we could determine an artifact folder by its name. All artifacts have -build- in their name. Hence the following function.</p>
<pre class="brush: groovy; title: ; notranslate">
private def isArtifactFolder(child) {
    child.uri.contains(&quot;-build-&quot;)
}
</pre>
<p>The next utility function is to actually delete a folder. The next function removes the provided path if we are not doing a dry run. If we did configure a dry run, we only print a message and do not actually do the delete. We again use the groovy template technology to create the query. Notice that the artifactory api uses the DELETE request.</p>
<pre class="brush: groovy; title: ; notranslate">
private def removeItem(path, child) {
    println &quot;folder: &quot; + path + child.uri + &quot; DELETE&quot;
    def binding = [repository: config.repository, path: path + child.uri]
    def template = engine.createTemplate('''/artifactory/$repository/$path''').make(binding)
    def query = template.toString()
    if (!config.dryRun) {
        def server = new RESTClient(config.server)
        server.delete(path: query)
    }
}
</pre>
<p>The last piece of the puzzle is the recursive function to check a folder for subfolders and give the command to remove a folder if it is in the list of folder to be removed. The next code block shows this function.</p>
<pre class="brush: groovy; title: ; notranslate">
def cleanArtifactsRecursive(path) {
    def deleteCounter = 0
    JSON json = folderInfo(path)
    json.children.each {child -&gt;
        if (child.folder) {
            if (isArtifactFolder(child)) {
                config.versionsToRemove.each {toRemove -&gt;
                    if (child.uri.startsWith(toRemove)) {
                        removeItem(path, child)
                        deleteCounter++
                    }
                }
            } else {
                if (!child.uri.contains(&quot;ro-scripts&quot;)) {
                    deleteCounter += cleanArtifactsRecursive(path + child.uri)
                }
            }
        }
    }
    return deleteCounter
}
</pre>
<p>The code is available online through github, check the references.</p>
<h2>References</h2>
<dl>
<dt><a href="http://blog.jteam.nl/2011/08/01/cleaning-up-your-maven-repository">Cleaning up your maven repository</a></dt>
<dd>Other blogpost about groovy and cleaning your local maven repository automatically.</dd>
<dt><a href="http://www.jfrog.com/">Artifactory</a></dt>
<dd>Homepage of the creators of Artifactory, here you can also find commercial support</dd>
<dt><a href="http://wiki.jfrog.org/confluence/display/RTF/Artifactory%27s+REST+API">Artifactory REST api</a></p>
<dd>Documentation for the REST api that is provided by Artifactory</dd>
<dt><a href="https://github.com/jettro/small-scripts/blob/master/groovy/artifactory/Artifactory.groovy">The source code</a></dt>
<dd>Sourcecode of the script discussed in this article.</dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/10/03/cleaning-up-artifactory-with-a-groovy-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Documents the Pull Way</title>
		<link>http://www.gridshore.nl/2011/09/01/documents-the-pull-way/</link>
		<comments>http://www.gridshore.nl/2011/09/01/documents-the-pull-way/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 19:48:15 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/2011/09/01/documents-the-pull-way/</guid>
		<description><![CDATA[<p>Today I came across a column posted (in Dutch) on Webwereld entitled &#34;It&#8217;s a trap!&#34;. This column is responding to the recent decision at a LibreOffice/OpenOffice Workshop to put more effort into support for Microsoft&#8216;s proprietary OOXML format.</p> <p>Perhaps it is because I have been reading Pull. Perhaps it is because I have been [...]]]></description>
			<content:encoded><![CDATA[<p>Today I came across a column posted (in Dutch) on <a href="http://webwereld.nl/" title="Webwereld" target="_blank">Webwereld</a> entitled &quot;<a href="http://webwereld.nl/column/107786/its-a-trap---column-.html" title="It's a trap! (column)" target="_blank">It&#8217;s a trap!</a>&quot;. This column is responding to the <a href="http://www.osor.eu/news/support-for-proprietary-ooxml-format-spurs-open-source-suites-adoption" target="_blank">recent decision</a> at a LibreOffice/OpenOffice Workshop to put more effort into support for <a href="http://www.microsoft.com" title="Microsoft" target="_blank">Microsoft</a>&#8216;s proprietary <a href="http://en.wikipedia.org/wiki/Office_Open_XML" title="Office Open XML" target="_blank">OOXML</a> format.</p>
<p>Perhaps it is because I have been reading <a href="http://www.amazon.com/Pull-Power-Semantic-Transform-Business/dp/B00403NG2C/" title="Pull: The Power of the Semantic Web to Transform Your Business" target="_blank">Pull</a>. Perhaps it is because I have been working at a new company over the past year who are trying to address some related issues. But this column got me thinking about what the essence is of what we call documents nowadays and how this might change in the coming years.</p>
<p><span id="more-1188"></span><br />
<h1>It&#8217;s a trap! in short&#8230;</h1>
<p>For those of you who do not read Dutch, the point of the original column &quot;It&#8217;s a trap&quot; is that word processors as they are nowadays are simply a continuation of the evolution of the paper document, from clay tablet to an electronic view on preparing documents for printing on static paper. However, the author states, documents are moving more and more to being electronic entities living primarily on computers, independent of the static form of the paper document. In light of this he is surprised that the LibreOffice community wants to concentrate on adopting the &quot;enemy&quot; document format and try to challenge Microsoft on its own homeground, when that is just playing to Microsoft&#8217;s strength rather than trying to pull ahead of them in the area of the location- and medium independent document that just lives in the cloud.</p>
<h1>Semantic web</h1>
<p>Like I mentioned earlier, I&#8217;ve been working for a new company for the past year. This <a href="http://www.qiy.com" target="_blank">company</a> is trying to embrace part of the vision of the <a href="http://en.wikipedia.org/wiki/Semantic_Web" target="_blank">semantic web</a> as put forth in books like <a href="http://thepowerofpull.com/siegel/thoughts/who-is-the-worlds-first-blogger" target="_blank">David Siegel</a>&#8216;s Pull. As part of this new job I&#8217;ve been able to spend time thinking about the vision of Pull and how reversing the current model of interaction between companies and consumers will affect the way we think about personal data and data sharing.</p>
<p>The basic idea behind the semantic web is that it must be possible to interpret the meaning of (textual) resources and the relationships to other resources automatically and unambiguously. To that end these relationships are described formally in a (the?) semantic web, enabling software to reason about these relationships according to preset rules in order to deliver value to human users of the software.</p>
<p>Once you start thinking about it, the consequence of building and using a semantic web is that data is not the only thing that is important any more. In addition to data (which exists for human interpretation and consumption), formally formed data <em>about</em> data is very important: the <strong><em><u>metadata</u></em></strong>. This metadata, like a formal description of relationships, describes what data is about in a way that can be understood by machines. Metadata is what enables automated processing of data and as the amount and richness of metadata increases and is linked together in a semantic web, the more it will enable smart(er) software to process data in new and unusual ways. It will enable software to discover data in the cloud and even generate new data by combining existing data through actual understanding of that data.</p>
<h1>It&#8217;s a document, but not as we know it</h1>
<p>So when is a datum data and when is it metadata? That&#8217;s a good question. The answer is that it depends. Data is intended for humans and metadata for computers&#8230; but why shouldn&#8217;t humans know who the sender of an email is, just because that information is metadata? Or the other way around, why shouldn&#8217;t a computer try to make some sense of data, or try to perform some processing of data, just because the primary audience is human? Search engines do exactly that&#8230;</p>
<p>The upshot of it is that data can be data and can be metadata interchangeably, depending on the context. In other words, the role of data is not fixed but depends on how you happen to be treating it. Nothing new there, of course. Which is when I came across that column.</p>
<p>The column raises the question of whether LibreOffice should try to follow the OOXML format when the very nature of document storage and presentation is changing. That&#8217;s a good point, but in the light of the semantic web it&#8217;s not going far enough. Since data can be both data and metadata and metadata enables processing (such as presentation), I say the real question is: what is a document?</p>
<p>The point of a file format like the .DOC or the .DOCX formats is that they contain document data (i.e. contents), what users consider metadata (i.e. properties like the author), and application-specific metadata pertaining to the way applications are supposed to present data. All very nice and useful. But one of those three categories is only useful to applications that want to present the content exactly the way Word does. An application that wants to apply different formatting, or wants to read the contents out loud, or wants to do something completely different than presenting the contents on-screen or on paper is not interested in the Word instructions at all.</p>
<p>So here&#8217;s a question: what is really a document? Is it a file on a storage medium? Or is it just the contents and the application-independent metadata? Is it in any way interesting to include presentation hints in a document? After all, if you follow the visions of data pull and the semantic web, real value comes from making data application-agnostic and allowing each application to overlay any presentation that fits its purposes.</p>
<p>And that is the direction I think documents will start following more and more. Even in the original Web 1.0 the intention already existed that data only be described and display be left to the user agent. After having veered off the path in HTML 3 and 4, the web is now morphing into the transport medium for a worldwide system of applications forming (partially) dynamic SOA networks, whose entire possibility of existence is based on being able to process raw data without having to wade through superfluous bytes that are specific to one particular application. Application networks like that are based on location-agnostic data with plenty of application-independent metadata to allow for all sorts of processing without binding to a specific application.</p>
<p>So I think that in the future our notion of a document will change completely. I think that we will move to a separation of content and semantic data from anything else, meaning that we will be divorcing documents from the applications that process them. We will even divorce documents from presentation forms and formats, so that the distinction between a Word document, a PDF, a spreadsheet, a (NoSQL) database of facts and relations, an MP3 recording of the contents and a steganographic encoding of some piece of abstract art will vanish and the informational content of the document will depend only on the application doing the processing (note that &quot;informational content&quot; is not the same as &quot;semantics&quot;).</p>
<h1>Oh, by the way&#8230;</h1>
<p>The column that inspired this blog was wondering whether or not the LibreOffice community should invest effort in becoming (more) compatible with the OOXML format and so emulate MS Office. Contrary to what you might be thinking, I feel that the answer given by that column is wrong. Not that I think that the goal should be to become fully OOXML-compatible, because I do feel the very notion of &quot;document&quot; and &quot;document format&quot; should change. But in the world that I think we are moving towards, the value of an application will not be in its compatibility with one data format but in how much value it creates for a user in the way it interprets and (re)processes the basic data and metadata.</p>
<p>So how does this relate to LibreOffice and their OOXML compatibility? Well, LibreOffice could stand to start offering more value as an office suite. Simply put, LibreOffice sucks as an office suite. It wasn&#8217;t so bad when Microsoft Office was still in the pre-2007 releases and documents from MS Office sucked in the same way as those from OpenOffice. But with Office 2007, Microsoft took a huge leap ahead of all the alternatives out there. And the difference isn&#8217;t in any technical improvement they made either; Microsoft didn&#8217;t add any great new technical functionalities, any huge new editing or DTP facilities or anything to do with the document <em>content</em>. But they did invest a lot in a number of document looks and feels (designed by graphics designers) that make it possible to create good-looking documents very simply (i.e. to present the content in an attractive way with little effort). A vast improvement over documents from other Office suites (including earlier versions of MS Office), which produced documents whose appearance sucked unless you put in A LOT of effort. In other words, Microsoft put a lot of effort into how they processed and presented the basic content of each file and so added a lot of value for the end user rather than adding useless functionality that nobody needs like they did in earlier releases. Their concentration on adding this value means MS Office is now a far better document processor than LibreOffice. And in that sense, yes, the LibreOffice community should definitely try to emulate Microsoft Office far more than it is doing now. Not for the document format, but for the value the office suite adds as a document interpreter.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/09/01/documents-the-pull-way/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cleaning up your maven repository with groovy</title>
		<link>http://www.gridshore.nl/2011/08/01/cleaning-up-your-maven-repository-with-groovy/</link>
		<comments>http://www.gridshore.nl/2011/08/01/cleaning-up-your-maven-repository-with-groovy/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 09:25:21 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[groovy and grails]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1165</guid>
		<description><![CDATA[<p>Ever looked at the space used by your maven repository? Think that this is to much? Start reading the blog post I wrote on my employers blog about a groovy script that you can use to clean your local maven repository. It removes old snapshots stored in your repo as well as old versions [...]]]></description>
			<content:encoded><![CDATA[<p>Ever looked at the space used by your maven repository? Think that this is to much? Start reading the blog post I wrote on my employers blog about a groovy script that you can use to clean your local maven repository. It removes old snapshots stored in your repo as well as old versions of artifacts.</p>
<p><a href="http://blog.jteam.nl/2011/08/01/cleaning-up-your-maven-repository">http://blog.jteam.nl/2011/08/01/cleaning-up-your-maven-repository</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/08/01/cleaning-up-your-maven-repository-with-groovy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Combining java and Node.js through redis pub/sub and a json remote interface</title>
		<link>http://www.gridshore.nl/2011/07/28/combining-java-and-node-js-through-redis-pubsub-and-a-json-remote-interface/</link>
		<comments>http://www.gridshore.nl/2011/07/28/combining-java-and-node-js-through-redis-pubsub-and-a-json-remote-interface/#comments</comments>
		<pubDate>Thu, 28 Jul 2011 10:11:16 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Axon Framework]]></category>
		<category><![CDATA[Frontend Technology]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[server technology]]></category>
		<category><![CDATA[axonframework]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[redis]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1163</guid>
		<description><![CDATA[<p>Recently I have been doing a lot with Node.js. It is a nice server technology that enables you to program on the server like you program on the client. Wouldn&#8217;t it be nice to create a java based business logic backend but a light weight client and server backend. Communication between node.js and java [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I have been doing a lot with Node.js. It is a nice server technology that enables you to program on the server like you program on the client. Wouldn&#8217;t it be nice to create a java based business logic backend but a light weight client and server backend. Communication between node.js and java is done in two ways in the sample. We use http and json for querying the data and for providing new data. Next to that I have an event system that pushes events with new data to the clients using nowjs. The following image gives you an idea about the overall solution.</p>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://www.gridshore.nl/wp-content/uploads/NodejsAxonRedisBlogpost.jpg" alt="Overview solution" border="0" width="551" height="323" /></p>
<p>If you want to find out more about this sample read on.</p>
<p><span id="more-1163"></span><br />
<h2>Introducing the sample</h2>
<p>The sample is based on the famous address book from the axonframework project. We reuse the axon sample and create a rest like interface that returns json to the clients. The source code is in the rest-ui project within the axonframework source tree under samples. This project also contains the listener code for the Contact and Address based events. The listeners listen for events and publish content from these events to the redis pub/sub mechanism. More on this in the later sections.</p>
<p>The other part of the sample is a node.js application. This application makes use of the rest api to obtain the data via http requests. Events about data changes are received through redis, using the pub/sub mechanism. The node.js application is available on Github. If you want to follow along, you can find the sources here:</p>
<p><a href="https://github.com/jettro/axon-addressbook-nodejs">https://github.com/jettro/axon-addressbook-nodejs</a><br/><br />
<a href="http://code.google.com/p/axonframework/source/browse/trunk#trunk%2Fsample%2Faddressbook%2Frest-ui">http://code.google.com/p/axonframework/source/browse/trunk#trunk%2Fsample%2Faddressbook%2Frest-ui</a></p>
<p>The following screen dump gives you an idea about the application.</p>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://www.gridshore.nl/wp-content/uploads/Screen-Shot-2011-07-25-at-19.06.57.png" alt="Screen Shot 2011 07 25 at 19 06 57" border="0" width="600" height="470" /></p>
<p>In the screen you see the list of contacts. You can add a new contact, change the name of a contact and add addresses to contacts. On the right you see the messages pane. Here you receive messages about new contacts that have been created, changed or deleted.</p>
<p>Now let us have a look at some of the code. We start with the java backend and then continue with the node.js part.</p>
<h2>The java part of the sample</h2>
<p>Numerous blogs have been written about rest based clients using spring mvc. Therefore I do not want to lose to much time in that area. Most important spring configuration is within the web.xml and the <a href="http://code.google.com/p/axonframework/source/browse/trunk/sample/addressbook/rest-ui/src/main/webapp/WEB-INF/spring/dispatcher-config.xml">dispatcher-config.xml</a>. In the web.xml we configure that every request is going to the spring dispatcher. We do not have status resources, only json responses. Within spring we make use of annotation to configure the beans. To be able to respond with json we make us of Jackson to transform beans into json objects. All pretty straightforward spring. Check the config file for yourself if you want to see how it works.</p>
<p>Next step is the controller that handles all the requests.</p>
<h3>Handling requests in the Cntroller</h3>
<p>The Controller handles the following requests:</p>
<ul>
<li>/contacts : GET, returns the list of all contacts</li>
<li>/contacts : POST, creates a new contact</li>
<li>/contacts : PUT, changes an existing contact</li>
<li>/contacts : DELETE, removes a contact</li>
<li>/contacts/{identifier} : GET, returns the details of a contact</li>
<li>/contacts/{identifier}/address : PUT, creates a new address or updates an existing one based on address type</li>
<li>/contacts/{identifier}/address : DELETE, removes the address of provided type</li>
</ul>
<p>Let us have a look at one of the requests to show the flow. For example we take the request for details. The following code block shows the complete method.</p>
<pre class="brush: java; title: ; notranslate">
@RequestMapping(value = &quot;{identifier}&quot;, method = RequestMethod.GET)
public @ResponseBody Map&lt;String, Object&gt; details(@PathVariable String identifier) {
    List&lt;AddressEntry&gt; addressesForContact = repository.findAllAddressesForContact(identifier);
    String name;
    if (addressesForContact.size() &gt; 0) {
        name = addressesForContact.get(0).getName();
    } else {
        name = repository.loadContactDetails(identifier).getName();
    }
    Map&lt;String, Object&gt; map = new HashMap&lt;String, Object&gt;();
    map.put(&quot;addresses&quot;, addressesForContact);
    map.put(&quot;identifier&quot;, identifier);
    map.put(&quot;name&quot;, name);
    return map;
}
</pre>
<p>The RequestMapping annotation tells spring which requests need to be mapped to this method. The controller already maps all /contacts to this controller. The {identifier} now maps everything with a url like /contacts/{identifier} to this method, as long as it is a GET request. This identifier is also used as a parameter for the method. With the @PathVariable we tell spring to take the value for this parameter from the url or Path that was requested. The final annotation in the method declaration is the @ResponseBody. This tells spring to use the return value as the response body, so not as the name of the view to use. We have already configured to use jackson to transform the response body into json. In the code of the controller you see we return a map with three objects in it. A list of addresses, an identifier of the contact and the name of the contact. The json coming out of this is:</p>
<p>{<br />
    &quot;name&quot;:&quot;Jettro&quot;,<br />
    &quot;addresses&quot;:[<br />
    {<br />
        &quot;name&quot;:&quot;Jettro&quot;,<br />
        &quot;identifier&quot;:&quot;82b4fef5-3389-440d-8893-6831a64e200d&quot;,<br />
        &quot;addressType&quot;:&quot;PRIVATE&quot;,<br />
        &quot;streetAndNumber&quot;:&quot;Feyenoordlaan 010&quot;,<br />
        &quot;zipCode&quot;:&quot;3000AA&quot;,<br />
        &quot;city&quot;:&quot;Rotterdam&quot;<br />
    }],<br />
    &quot;identifier&quot;:&quot;82b4fef5-3389-440d-8893-6831a64e200d&quot;<br />
}</p>
<p>That is what you need to know about the rest api that I have created. If you want to have a look at the controller, <a href="http://code.google.com/p/axonframework/source/browse/trunk/sample/addressbook/rest-ui/src/main/java/org/axonframework/examples/addressbook/rest/ContactsController.java">check here</a>. The next step is about the listeners that listen for axon events related to the contacts and addresses and store information in redis.</p>
<h3>Listening for events</h3>
<p>We register listeners with axon for the contact related events as well as address related events. This is very easy with the annotations provided by the axonframework. The following code block shows how we register an event listener for the ContactCreatedEvent.</p>
<pre class="brush: java; title: ; notranslate">
@EventHandler
public void handleContactCreatedEvent(ContactCreatedEvent event) {
    ContactEntry value = new ContactEntry();
    value.setName(event.getName());
    value.setIdentifier(event.getContactIdentifier());
    Message&lt;ContactEntry&gt; message = new Message&lt;ContactEntry&gt;(&quot;contact-created&quot;, value);
    publisher.publish(message);
}
</pre>
<p>Notice the @EventHandler annotation. This registers the listener with axon. As you can see we take the information from the provided event and put it in a Message object. The message object contains a type and the content. The type can be used at the receiving side to better understand how to handle the received event. The publisher is auto injected by spring. In my case it is a redis publisher.</p>
<h3>Publishing to redis</h3>
<p>A library to talk with redis is <a href="https://github.com/xetorthio/jedis">jedis</a>. Jedis makes use of a pool which is configured in spring. Check the listener-context.xml to see how it works. Jedis does not have the most obvious api but it works. The following code block shows how a message is published to redis.</p>
<pre class="brush: java; title: ; notranslate">
public void publish(Message&lt;?&gt; message) {
    StringWriter writer = new StringWriter();
    try {
        mapper.writeValue(writer, message);
    } catch (IOException e) {
        logger.warn(&quot;Problem while writing ContactEntry to a string writer&quot;, e);
        return;
    }

    Jedis jedis;
    try {
        jedis = jedisPool.getResource();
    } catch (JedisConnectionException e) {
        logger.debug(&quot;Could not obtain redis connection from the pool&quot;);
        return;
    }
    try {
        jedis.publish(&quot;nl.axonframework.examples.addressbook&quot;, writer.toString());
    } finally {
        jedisPool.returnResource(jedis);
    }
}
</pre>
<p>The code is not very complicated. The important part here is that we use a jackson provided ObjectMapper to map the provided message to a json representation. Then you can see the nice jedis api at work. As you can see we publish a message to a queue. Our node.js client will subscribe to this queue. That is have the redis publish/subscribe works. Not very hard is it?</p>
<p>That is it for the java side. We now know how to get data using the rest api and we know where to get information about events that take place. Let us move on to the node.js side of the application.</p>
<h2>The Node.js part of the sample</h2>
<p>I do not want to go in setting up a node.js project. Do not want to explain all the different libraries that I use. I have written other blog posts on node.js that I do not want to copy. The most important one is this:</p>
<p><a href="http://blog.jteam.nl/2011/04/18/learning-node-js/">http://blog.jteam.nl/2011/04/18/learning-node-js/</a></p>
<p>The node.js project uses 4 libraries:</p>
<ul>
<li>express &#8211; doing the mvc part of the web application</li>
<li>jade &#8211; view templating</li>
<li>now &#8211; server push to the client (will explain this in a bit more detail)</li>
<li>redis &#8211; for redis interaction</li>
<p> </ul>
<h3>Project layout</h3>
<p>The public folder contains all the client related files like javascript, css and images. I will explain one file in here later on when discussing node.js. The test folder contains the test for the ContactRepository. Using this test helped me to verify that the integration between the java backend and the node.js application is working without having to start the application and go through the browser to check all requests. The views folder contains all the jade templates. Check mentioned blog post to find more information on jade. The app.&#8217;s initializes the application and maps all possible requests to methods in the ContactController. The controller knows where to get the data from and what page to render. The repository is responsible for obtaining data from the rest api on the java side.</p>
<h3>Initializing the node.js application</h3>
<p>As mentioned the app.js is the start of the application. Let us have a look at the different parts.</p>
<pre class="brush: jscript; title: ; notranslate">
var ContactController = require('./ContactController');
var repository = require('./ContactRepository').createRepo('localhost',8080);
var contactController = new ContactController(repository);
</pre>
<p>This part initializes our components. We will have a look at the createRepo method later on. But notice that we initialize the controller with an instance of the repository.</p>
<pre class="brush: jscript; title: ; notranslate">
app.get('/', contactController.listContacts);
app.get('/contact/new', contactController.newContactShowForm);
app.post('/contact/new', contactController.newContactPostForm);
app.get('/contact/:identifier',contactController.contact);
app.get('/contact/:identifier/edit',contactController.changeContactShowForm);
app.post('/contact/:identifier/edit',contactController.changeContactPostForm);
app.get('/contact/:identifier/delete',contactController.deleteContactShowForm);
app.post('/contact/:identifier/delete',contactController.deleteContactPostForm);
app.get('/contact/:identifier/address/new',contactController.newAddressShowForm);
app.post('/contact/:identifier/address/new',contactController.newAddressPostForm);
app.get('/contact/:identifier/address/:addressType/edit',contactController.changeAddressShowForm);
app.post('/contact/:identifier/address/:addressType/edit',contactController.changeAddressPostForm);
app.get('/contact/:identifier/address/:addressType/delete',contactController.deleteAddressShowForm);
app.post('/contact/:identifier/address/:addressType/delete',contactController.deleteAddressPostForm);
</pre>
<p>These are all the possible requests. The urls are easy to understand. As you can see, all urls are mapped to a method of the contactController</p>
<pre class="brush: jscript; title: ; notranslate">
var Now = require('now');
var everyone = Now.initialize(app);

var redis = require(&quot;redis&quot;),
    client = redis.createClient();

client.on(&quot;error&quot;, function (err) {
    console.log(&quot;Error %s&quot;, err);
});

client.on(&quot;message&quot;, function (channel, message) {
    everyone.now.receiveContact(message);
});
client.subscribe(&quot;nl.axonframework.examples.addressbook&quot;);
</pre>
<p>This is the harder bit. This has to do with receiving messages using the redis pub/sub mechanism and sending it to all connected clients using the nowjs library. I&#8217;ll discuss the now.js part later on.</p>
<h3>Request handling</h3>
<p>By using the repository object the controller becomes very easy. We only have to obtain the right data and render the right view. The most basic method is showing a list of contacts. The following code block shows the complete method.</p>
<pre class="brush: jscript; title: ; notranslate">
ContactController.prototype.listContacts = function(req, res) {
    repository.listContacts(function(contacts) {
        res.render('index', {locals: {contacts: contacts, nowjs: true}});
    });
};
</pre>
<p>Notice that we use a callback that is provided to the repository listContact method. Check that we provide the list of contacts to the view, together with a second parameter called nowjs. Remember this, on this page we enable nowjs, meaning that we can receive messages when looking at this page. Other methods are similar, have a look at the method that handles submitting a form to create a new contact.</p>
<pre class="brush: jscript; title: ; notranslate">
ContactController.prototype.newContactPostForm = function(req, res) {
    repository.newContact(req.body.new_name, function(code, message) {
        if (code == &quot;ok&quot;) {
            res.redirect(&quot;/&quot;);
        } else {
            res.render('newcontact', {locals: {error:message}});
        }
    });
};
</pre>
<p>In line 2 we obtain the form parameter <em>new_name</em> from the request body. Than we create a new contact. The callback method expects a code indicating whether the submission of the new contact was ok. If not, we render the form again with the error message. This happens when we try to create a contact with a name that already exists. The following image shows the screen with an error message.</p>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://www.gridshore.nl/wp-content/uploads/Screen-Shot-2011-07-28-at-10.07.30.png" alt="Screen showing the error message" border="0" width="600" height="459" /></p>
<p>Next up is the communication with a rest based application</p>
<h3>The Repository as a client to a rest application</h3>
<p>During the initialization of the application I already mentioned the createRepo method of the ContactRepository. The following code block shows the method. As you can see it initializes a repository with the default values for host and port.</p>
<pre class="brush: jscript; title: ; notranslate">
ContactRepository.createRepo = function(host, port) {
    var repo = new ContactRepository();
    repo.host = host;
    repo.port = port;
    return repo;
};
</pre>
<p>Again most of the interaction with the backend is the same. Therefore I use the create contact again as an example. I have created tests for all the repository methods. Let us have a look at the test first.</p>
<pre class="brush: jscript; title: ; notranslate">
function testNewContact() {
    logTestName(&quot;New contact&quot;);
    repository.newContact(&quot;My Test&quot;, function(code, message) {
        assert.equal(&quot;ok&quot;, code, &quot;This should be no problem and an ok should be returned: &quot; + code);
        // Check if the amount of contacts is increased
        repository.listContacts(function(contacts) {
            assert.equal(numContacts + 1, contacts.length, &quot;Number of contacts is not right, create did not work: &quot; + contacts.length);
            testAddAddress();
        });
    });
}
</pre>
<p>Notice that we check the return code and that the amount of contacts is increased. The following code block shows the implementation of the method of the repository.</p>
<pre class="brush: jscript; title: ; notranslate">
ContactRepository.prototype.newContact = function(name, callback) {
    var opts = createHttpRequestOpts('/contacts', 'POST');

    var req = http.request(opts, function(res) {
        res.setEncoding('utf8');
        res.on('data', function(data) {
            if (res.statusCode != 200) {
                console.log(data);
                callback('error', 'Maybe the name is already taken?');
            } else {
                callback('ok', 'The new contact has been send')
            }
        });
    });

    var contact = {};
    contact.name = name;

    req.write(JSON.stringify(contact));
    req.end();
};

function createHttpRequestOpts(path, method) {
    return {
        host: host,
        port: port,
        path:path,
        headers:{'Accept':'application/json','Content-Type':'application/json'},
        method: method
    };
}
</pre>
<p>I use the nodejs provided http request. Within the help function the opts object is created with the host, port, path, method and the headers. The headers are important to request json. Of course we provide a callback to handle the http response. Everything not 200 is an error as a response code. Here we call the provided callback to the repository method with the ok or error code. At the end of the method we do the actual request creation with the json request.</p>
<p>The final bit is the server push using the now.js library.</p>
<h3>Server push using now.js</h3>
<p>Node.js comes with a socket.io library. This makes server push very easy. Still it can be a lot easier. That is when using <a href="http://nowjs.com/">now.js</a>. Now.js enables you to call methods on the client that are actually on the server and vise versa. Let us have a look at the code for sending messages to the client when a redis event is received again.</p>
<pre class="brush: jscript; title: ; notranslate">
var Now = require('now');
var everyone = Now.initialize(app);
client.on(&quot;message&quot;, function (channel, message) {
    console.log(&quot;Received message: %s&quot;, message);
    everyone.now.receiveContact(message);
});
</pre>
<p>The important part here is the initialization of now and the line with everyone.now.receiveContact. Now we will call the connected clients method receiveContact and provide the message. Of course we need some client code for this. This code is available in the local.js file in the public folder.</p>
<pre class="brush: jscript; title: ; notranslate">
$(document).ready(function() {
    now.receiveContact = function(data) {
        var message = JSON.parse(data);
        var toWrite;
        switch(message.type) {
            case 'contact-removed':
                toWrite = &quot;Contact removed&quot;;
                break;
            case 'contact-created':
                toWrite = &quot;Contact with name &quot; + message.content.name + &quot; created&quot;;
                break;
            case 'contact-changed':
                toWrite = &quot;Contact changed name to &quot; + message.content.name;
                break;
            case 'address-created':
                toWrite = &quot;Added address of type &quot; + message.content.addressType + &quot; to contact &quot; + message.content.name;
                break;
            case 'address-removed':
                toWrite = &quot;Removed address of type &quot; + message.content.addressType + &quot; to contact &quot; + message.content.contact.name;
                break;
        }
        $(&quot;#messages&quot;).prepend(&quot;&lt;div&gt;&quot; + toWrite + &quot; &lt;/div&gt;&quot;);
    };
});
</pre>
<p>As you can see, we construct the message based on the type of the message and prepend a new div within the #messages div. Really that is all there is to it.</p>
<h2>Last remarks</h2>
<p>That is it. Again a long blog item. Hope you got some new knowledge out of it. Feel free to post comments if you have questions or even better improvements.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/07/28/combining-java-and-node-js-through-redis-pubsub-and-a-json-remote-interface/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creating presentations with Node.js</title>
		<link>http://www.gridshore.nl/2011/06/15/creating-presentations-with-node-js/</link>
		<comments>http://www.gridshore.nl/2011/06/15/creating-presentations-with-node-js/#comments</comments>
		<pubDate>Wed, 15 Jun 2011 14:24:15 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[server technology]]></category>
		<category><![CDATA[express]]></category>
		<category><![CDATA[jade]]></category>
		<category><![CDATA[node.js]]></category>
		<category><![CDATA[nodejs]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1157</guid>
		<description><![CDATA[<p>I am learning about Node.js. While learning I usually create a few demo&#8217;s. Another thing I am attending a training for is learning how to give good presentations. I had to prepare a 10 minute presentation. Would be nice if I could combine the learning about Node.js with the 10 minute presentation. I decided [...]]]></description>
			<content:encoded><![CDATA[<p>I am learning about Node.js. While learning I usually create a few demo&#8217;s. Another thing I am attending a training for is learning how to give good presentations. I had to prepare a 10 minute presentation. Would be nice if I could combine the learning about Node.js with the 10 minute presentation. I decided to create a Node.js application to give the presentation. So no Keynote for me this time.</p>
<p>In this blog post I present you an additional sample, focussed on creating presentations as a programmer. I&#8217;ll use a few node.js modules: Jade, Express.</p>
<p>On my employers blog I wrote an extensive article about Node.js, you can have a look at the article as well.</p>
<p><a href="http://blog.jteam.nl/2011/04/18/learning-node-js/">http://blog.jteam.nl/2011/04/18/learning-node-js/</a><br/><span id="more-1157"></span><br />
<h2>Requirements</h2>
<p>I want to have a tool that supports multiple presentations that can all be shown in a browser. I do not consider a lot of browsers. I like the css support and the full screen view of chrome on the Mac. Therefore I test my work with Chrome only. I guess most of the features work on other browsers as well, some small issues might arise. A big advantage of using the browser is that you have lots of libraries available to create nice looking slides.</p>
<p>The tool needs to be developer friendly, therefore slides are created with code. No hot deploys, no tools to just enter slides. The slides are within the code. This is not an end user tool, this is a developer tool.</p>
<p>Each presentation consists of a title, should be able to work with a chosen template and contains slides of course.</p>
<p>Giving or presenting the presentation should be easy as well. Therefore I want to be able to choose a slide, go to the next slide, the previous slide and the index of all presentations.</p>
<p>Going to a different presentation means using another url. For each presentation we provide a path and the slide index. A url for a presentation skills presentation than becomes:</p>
<pre>
<a href="http://dev.gridshore.nl:8018/presentation/create-presentation-nodejs">http://dev.gridshore.nl:8018/presentation/create-presentation-nodejs</a>
</pre>
<p>The first slide in that presentation than becomes:</p>
<pre>
<a href="http://dev.gridshore.nl:8018/presentation/create-presentation-nodejs/slide/1">http://dev.gridshore.nl:8018/presentation/create-presentation-nodejs/slide/1</a>
</pre>
<p>The final feature that would be nice is generating a handout. For now this will be a print view in the browser, maybe a pdf. An overview with all the slides on one page will be here:</p>
<p><a href="http://dev.gridshore.nl:8018/presentation/create-presentation-nodejs/all">http://dev.gridshore.nl:8018/presentation/create-presentation-nodejs/all</a></p>
<h2>Chosen technologies</h2>
<p>A slide consists of content, layout and styling. I want to limit the amount of styling information in the content. Still I want to make it simple. Therefore I have chosen to use a template engine for the front-end. I have some experience with Jade, which seems to do the job fine. The styling is done using css and where necessary, with additional components. An example is presenting source code on a slide.</p>
<p>When working with a web application and a browser it is wise to have a way to handle requests. Express.js is a nice node.js framework to use for url handling. I&#8217;ll get back with some sample code later on.</p>
<p>Since we are creating a web application, we need style sheets and images. I also use jQuery and a few plugins to position elements, to handle keyboard commands and to show source code. Please refer to the references section if you need more information about one of the technologies.</p>
<h2>The solution</h2>
<h3>Project layout</h3>
<p>An express.js application consists of an app.js, a public folder and a views folder. The app.js is the start of the application that you call with the node executable. In the public folder we have the static web resources. It contains the stylesheets, client-side javascripts and other static resources. The views folder contains the layout.jade file and all the jade views. Within the images and the views folder we have a subfolder for each presentation. I prefer to use the same path as the path specified for the url for the presentation. More on this later.</p>
<p>The project now has two dependencies: expressjs and jade. I like to manage my dependencies with npm.</p>
<h3>Creating the presentation</h3>
<p>The presentation is created as a separate component, have a look at <a href="https://github.com/jettro/nodejs-presenter/blob/master/presentation.js">presentation.js</a>. It contains the title of the presentation, the urlIdentifier, a description and the slides. The urlIdentifier is used in the url when requesting the presentation in a browser. The slides are also components. You can find the slide component in <a href="https://github.com/jettro/nodejs-presenter/blob/master/slide.js">slide.js</a>. The slide contains an identifier and a title. The identifier is important, this is used to find the right jade view file. The following code block shows the creation of the sample presentation.</p>
<pre class="brush: jscript; title: ; notranslate">
var createPresentationNodejs = [];
createPresentationNodejs.push(new Slide(&quot;intro&quot;,&quot;Creating a presentation with Node.js&quot;));
createPresentationNodejs.push(new Slide(&quot;goal&quot;,&quot;Goal&quot;));
createPresentationNodejs.push(new Slide(&quot;requirements&quot;,&quot;Requirements&quot;));
createPresentationNodejs.push(new Slide(&quot;technology&quot;,&quot;technology&quot;));
createPresentationNodejs.push(new Slide(&quot;urlhandling&quot;,&quot;Configure url handling&quot;));
createPresentationNodejs.push(new Slide(&quot;handlerequests&quot;,&quot;Handle requests&quot;));
createPresentationNodejs.push(new Slide(&quot;viewcontent&quot;,&quot;View content&quot;));
createPresentationNodejs.push(new Slide(&quot;thefuture&quot;,&quot;The Future&quot;));
createPresentationNodejs.push(new Slide(&quot;questions&quot;,&quot;Questions&quot;));

presentationController.addPresentation(new Presentation(&quot;Creating a presentation with Node.js&quot;,&quot;create-presentation-nodejs&quot;,
	createPresentationNodejs,
    &quot;For my work I had to prepare a short presentation of around 10 minutes. I decided to create a tool to create presentation &quot; +
            &quot;with and present about it. This is the result, a short presentation showing some of the ideas.&quot;));
</pre>
<p>In the first lines you can see how we create the array of slides. The last few lines show how we add a new presentation to the presentationController. We get back to this presentationController later on. First we have to look at express and url handling.</p>
<h3>Express and url handling</h3>
<p>Express is a web framework for node.js. You can do lots of things, in this blog post I do not want to give to much basics. Check the blog post I wrote on my employers blog: <a href="http://blog.jteam.nl/2011/04/18/learning-node-js/">http://blog.jteam.nl/2011/04/18/learning-node-js</a>.</p>
<p>THe thing I do want to mention is the url mapping for GET and POST requests. These are important for the flow of the application. You can also see the way that the PresentationController is used. Have a look at the following code block</p>
<pre class="brush: jscript; title: ; notranslate">
var presentationController = new PresentationController();

app.get('/', presentationController.allPresentations);
app.get('/presentation/:urlIdentifier', presentationController.index);
app.get('/presentation/:urlIdentifier/slide/:id', presentationController.slide);
app.post('/presentation/:urlIdentifier/slide/:id', presentationController.command);
app.get('/presentation/:urlIdentifier/all', presentationController.allSlides);
</pre>
<p>Going to the root of the application gives a list over presentations. Asking the presentation with the urlIdentifier of the presentation gives an overview of the presentation. You can also ask the /all, this will give all the slides. Check the section about a slide handout for more information on this.</p>
<p>The handling of the POST request is for navigation. Within the slide you can enter n for next, p for previous, a number for a specific slide and enter for the next slide. This will result in a command on the server using the post request. Creating this request can be found in the layout.jade. It is a normal form for the action to the url of the current slide number. Using the command and the current slide number we can determine the slide to select. The next block shows the client code, handling the post request is discussed in the next section.</p>
<pre class="brush: plain; title: ; notranslate">
form(action=&quot;/presentation/&quot;+urlIdentifier+&quot;/slide/&quot;+numSlide,method=&quot;POST&quot;)
    input(type=&quot;text&quot;, size=&quot;100&quot;, name=&quot;command&quot;, id=&quot;command&quot;)
</pre>
<p>Now we have seen the url handling, let us move on to the logic in the PresentationController</p>
<h3>The presentation controller</h3>
<p>The presentation controller contains the logic to handle a request and send the response back to the requestor. The following code block shows the the handling for the request to show all available presentations.</p>
<pre class="brush: jscript; title: ; notranslate">
PresentationController.prototype.allPresentations = function(req, res) {
    res.render('index', {locals: {presentations:presentations}});
};
</pre>
<p>The presentations is an internal array for the presentation controller. They are passed to the &#8216;index&#8217; view. More on the view with jade in the next section. The following code block is slightly more advanced. It contains the logic to show one slide.</p>
<pre class="brush: jscript; title: ; notranslate">
PresentationController.prototype.slide = function(req, res) {
    var id = req.params.id;
    var presentation = obtainPresentation(req.params.urlIdentifier);
    var slide = presentation.slides[id - 1];
    res.render(presentation.urlIdentifier + '/slide/' + slide.identifier,
            {locals: {
                numSlide:req.params.id,
                totalSlide:presentation.slides.length,
                titleSlide:slide.title,
                urlIdentifier:presentation.urlIdentifier
            }});
};

function obtainPresentation(urlIdentifier) {
    var len = presentations.length;
    for (var i = 0; i &amp;lt; len; i++) {
        var presentation = presentations[i];
        if (urlIdentifier == presentation.urlIdentifier) {
            return presentation;
        }
    }
    throw &quot;Could not find the url: &quot; + urlIdentifier;
}
</pre>
<p>The code contains a helper function to determine the presentation to show a slide for. The presentation is obtained by the url identifier. The page is rendered by using the specific jade template that is stored using the urlIdentifier in the slides folder. The name of the jade template is the same as the identifier as stored in the slide object.</p>
<p>The last bit I want to discuss is the command handling. We have a small form at the bottom of the page. This form accepts commands. We support &#8216;n&#8217; or &#8216;next&#8217;, &#8216;enter&#8217;, &#8216;p&#8217; or &#8216;previous&#8217; and the number of a slide. These all navigate between the slides. We also have the &#8216;home&#8217; command. This redirects to the root of the application. Handling the different commands is done with a very easy if-the-else structure. The following code block shows the idea.</p>
<pre class="brush: jscript; title: ; notranslate">
PresentationController.prototype.command = function(req, res) {
    var id = req.params.id;
    var urlIdentifier = req.params.urlIdentifier;
    var command = req.body.command;
    var presentation = obtainPresentation(urlIdentifier);
    var numSlides = presentation.slides.length;

    if (command == 'next' || command == 'n' || command == '') {
        if (id &lt; numSlides) id++;
    } else if (command == 'previous' || command == 'p' || command == 'prev') {
        if (id &gt; 1) id--;
    } else if (command == 'home') {
        res.redirect('/');
        return;
    } else if (!isNaN(command)) {
        var commandNum = parseInt(command);
        if (commandNum &gt; 0 &amp;&amp; commandNum &amp;lt;= numSlides) id = commandNum;
    }

    res.redirect('/presentation/' + urlIdentifier + '/slide/' + id);
};
</pre>
<p>Enough about logic, let us move on to the view side and discuss templating using Jade.</p>
<h3>Little bit of jade</h3>
<p>Again I do not want to go into all the details of jade. Jade is a very condensed format for creating html pages. It integrates nicely with express. Data is passed from express to jade. Jade uses a layout file, you can also use partial rendering without a layout file. More on this in a next section. In this case we include the header and the footer in the layout file. Each slide is presented in its own jade template file. The following code block shows the jade template for the intro slide in the sample.</p>
<pre class="brush: plain; title: ; notranslate">
img(src='/images/' + urlIdentifier + '/logo.jpg')
div.heading author
div.heading Jettro Coenradie
img(src='/images/' + urlIdentifier + '/nature.jpg', class=&quot;shadow&quot;)
</pre>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://www.gridshore.nl/wp-content/uploads/Screen-shot-2011-06-15-at-12.09.47.png" alt="Screen shot 2011 06 15 at 12 09 47" border="0" width="600" height="536" /></p>
<p>Another nice thing about using the web browser as a tool is that you can use nice plugins available for websites to create your slides. A good example is showing source code. This is what the next section is about.</p>
<h3>Showing code</h3>
<p>To show source code I use a <a href="http://alexgorbatchev.com/SyntaxHighlighter">syntax highlighter from alex gorbatchev</a>. The client side library files are included in the public folder. Showing code in a jade template looks like this.</p>
<pre class="brush: plain; title: ; notranslate">
pre(class=&quot;brush: js&quot;)
    | app.get('/', function(req, res) {
    |     res.render('index',
    |         {locals: {slides:slide.allSlides()}});
    | });
    | app.get('/slide/:id', slide.index);
    | app.post('/slide/:id', slide.command);
script(type=&quot;text/JavaScript&quot;)
    | SyntaxHighlighter.all()
</pre>
<p><img style="display:block; margin-left:auto; margin-right:auto;" src="http://www.gridshore.nl/wp-content/uploads/Screen-shot-2011-06-15-at-12.15.32.png" alt="Screen shot 2011 06 15 at 12 15 32" border="0" width="600" height="336" /></p>
<h3>Creating a slide handout</h3>
<p>One of the requirements of a presentation is often to have the slides available as a pdf document or other format that is able to share the slides. The path I am taking is using one page for a presentation that contains the complete presentation. I would love to have a pdf generated from the webpage. But for now this is one step to far. I did have a look at using node.js child processes to run a command line tool called wkhtmltopdf. I want to do some more experimentation here. Will get back when I have a good solution. Beneath are some references if you want to try it out yourself.</p>
<ul>
<li><a href="http://blog.darkhax.com/2010/11/29/2-node-js-apps-that-showed-me-the-light">http://blog.darkhax.com/2010/11/29/2-node-js-apps-that-showed-me-the-light</a></li>
<li><a href="http://code.google.com/p/wkhtmltopdf/">http://code.google.com/p/wkhtmltopdf/</a></li>
<p> </ul>
<p>To be able to create one page with all the slides I made use of the partial rendering of jade and express. The idea is to pass a the presentation to a view. The view steps over all the slides in the presentation and renders the views on one page. The following code block shows the view (all.jade).</p>
<pre class="brush: plain; title: ; notranslate">
div#All slides
h2 #{presentation.title}
ul
    - each slide in presentation.slides
        - var slideTemplate = presentation.urlIdentifier + '/slide/' + slide.identifier
        .slideAll
            - if(typeof(slide.title) != &quot;undefined&quot;)
                div.title #{slide.title}
            !=partial(slideTemplate, {'urlIdentifier':presentation.urlIdentifier})
</pre>
<p>The &#8220;presentation&#8221; object is provided by the express component. From this object we obtain the path in the views folder. The presentation object also contains the slides. Each slide has its own identifier. Using the slide identifier and the urlIdentifier we can find the jade template to render. The trick is in the last line <strong>!=partial(&#8230;)</strong>. This tells the engine to include the specific slide templates in he current view.</p>
<h2>The demo</h2>
<p>There is an online demo available at: <a href="http://dev.gridshore.nl:8018/">http://dev.gridshore.nl:8018/</a>. It contains only one presentation at the moment. But that is enough to get an idea. This blogpost also contains two screen dumps.</p>
<h2>The future</h2>
<p>I want to integrate the pdf generation within the application. I have some hints, but not the complete solution. Maybe extend the tool in a way that you can create new presentations on the fly, but I do not want to make an alternative to presentation tools that are already there. I also want to add more controls, would be nice to be able to use the arrow keys and maybe support remote controls that way.</p>
<h2>References</h2>
<ul>
<li><a href="http://nodejs.org/">http://nodejs.org/</a> &#8211; Node.js home page</li>
<li><a href="http://expressjs.com/">http://expressjs.com/</a>- Express.js</li>
<li><a href="http://jade-lang.com/">http://jade-lang.com/</a>- Jade</li>
<li><a href="http://alexgorbatchev.com/SyntaxHighlighter">http://alexgorbatchev.com/SyntaxHighlighter</a>- Code beautifier</li>
<li><a href="https://github.com/jettro/nodejs-presenter">https://github.com/jettro/nodejs-presenter</a> &#8211; the code for the sample.</li>
<li><a href="http://blog.darkhax.com/2010/11/29/2-node-js-apps-that-showed-me-the-light">http://blog.darkhax.com/2010/11/29/2-node-js-apps-that-showed-me-the-light</a> &#8211; inspiration for pdf export.</li>
<li><a href="http://code.google.com/p/wkhtmltopdf/">http://code.google.com/p/wkhtmltopdf/</a> &#8211; want to use for pdf export.</li>
<p> </ul>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/06/15/creating-presentations-with-node-js/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Coming up in the Axon Framework</title>
		<link>http://www.gridshore.nl/2011/05/11/coming-up-in-the-axon-framework/</link>
		<comments>http://www.gridshore.nl/2011/05/11/coming-up-in-the-axon-framework/#comments</comments>
		<pubDate>Wed, 11 May 2011 09:02:32 +0000</pubDate>
		<dc:creator>Allard</dc:creator>
				<category><![CDATA[Axon Framework]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[Domain Driven Design]]></category>
		<category><![CDATA[test driven development]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/2011/05/11/coming-up-in-the-axon-framework/</guid>
		<description><![CDATA[<p>Recently, I released Axon Framework 1.0. Instead of it being an opportunity to take a small break, things have gone into a higher gear instead. In this article, I give a sneak preview of what’s coming up in and around Axon Framework.</p> <p> More test fixtures <p>Testing is obviously very important. Axon already has [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, I released Axon Framework 1.0. Instead of it being an opportunity to take a small break, things have gone into a higher gear instead. In this article, I give a sneak preview of what’s coming up in and around Axon Framework.</p>
<p><span id="more-1153"></span><br />
<h2>More test fixtures</h2>
<p>Testing is obviously very important. Axon already has test fixtures to test your command handling components using an easy-to-use given-when-then fixture. But the command handling component is not the only component with potentially complex business logic.</p>
<p>Axon 1.1 will include a similar fixture for testing Sagas. The big difference between a Command Handler and a Saga is that the Saga responds to Events and takes decisions based on them. Quite often, the aspect of time is important. For example, if an invoice is not paid within 30 days, the Saga must send a command to cancel or block an Order. The Saga test fixture allows you to write code like this:</p>
<pre>
<pre class="brush: java; title: ; notranslate">fixture.givenAggregate(orderAggregate).published(new OrderCreatedEvent())
       .andThenAggregate(invoice).published(new InvoiceSentEvent())

       .whenTimeElapses(Duration.standardDays(31))

       .expectDispatchedCommands(new BlockOrderCommand());
</pre>
</pre>
<p>This allows you to write human-readable test that define what the behavior should be when certain things happen, or even when they don’t happen.</p>
<p>Work on these fixture is still in progress, but a sneak preview is available in the 1.1-SHAPSHOT version already. Look for the AnnotatedSagaTestFixture class, give it the class you want to test and you are ready to start testing.</p>
<h2>Redis event store</h2>
<p>Redis is a very nice and full-featured key-value store. Instead of values being plain blobs, Redis allows for lists, sets, maps (called hashes) and even ordered sets. There is also a pub/sub mechanism in place and the API supports the implementation of message queues.</p>
<p>All in all, this makes Redis a very nice candidate for an Event Store implementation. We have already spent some time investigating the API and the level of consistency guarantees that Redis can offer. They match very well with what one would expect from an Event Store. We’ll be spending some more time on it before we decide whether to implement a full-blown Event Store, or not.</p>
<h2>Distributed command bus</h2>
<p>Scalability is obviously one of the reasons to choose for CQRS. Having components that only work within a single JVM doesn’t really help. I have done a small proof-of-concept with a Distributed version of the Command Bus. So far, the results look really good.</p>
<p>This Command Bus implementation allows commands to be distributed over a cluster of machines for execution. Instead of blindly sending commands to random machines, it uses the Consistent Hashing algorithm to make sure that commands for the same Aggregate will end up on the same machine. If a machine drops, the load is taken over by the remaining machines. You can even –at runtime- add another machine to the cluster and have it take over some of the load. This means you can dynamically adapt your cluster size to meet the needs of that specific moment, without any single-point-of-failure.</p>
<p>The distributed command bus is still in the proof-of-concept phase, but work on the real version will start very soon. I will also build a small application that allows you to see it at work.</p>
<h2>2-day “full-immersion” training</h2>
<p>Spreading knowledge on CQRS and the Axon Framework has always been on the agenda. In the past few months, I have given suite a number of presentations and 1-day workshops. Although they are nice to do, there is too little time to really dive into the matter. That’s why I have decided to go for a 2-day training.</p>
<p>This two day training is a little different that what you’re used to. Instead of doing a training over 2 days from 9AM to 5PM, this training is 32 hours in a row. Okay, admitted, this includes a few hours of eating and sleeping as well. The training takes place in a hotel in the beautiful “Utrechse Heuvelrug” area in The Netherlands. It’s 2 days, all-in (overnight stay and meals). The idea behind this concept is that we’ll be able to really dive deep into the concepts and get to the bottom of things. So after dinner on the first day, there is time for coding as well as informal chatting at the hotel bar.</p>
<p>The training covers the basic concepts of DDD and CQRS, but also allows you to really get your hands dirty. The first training has been scheduled for June 23rd and 24th 2011. For more information about this training, visit the training page: <a href="http://www.jteam.nl/training/workshop/2-day-CQRS-and-Axon-Immersion-Training.html">http://www.jteam.nl/training/workshop/2-day-CQRS-and-Axon-Immersion-Training.html</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/05/11/coming-up-in-the-axon-framework/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

