<?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>Tue, 12 Mar 2013 19:47:14 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Introducing a query tool for elasticsearch</title>
		<link>http://www.gridshore.nl/2013/03/12/introducing-a-query-tool-for-elasticsearch/</link>
		<comments>http://www.gridshore.nl/2013/03/12/introducing-a-query-tool-for-elasticsearch/#comments</comments>
		<pubDate>Tue, 12 Mar 2013 19:47:14 +0000</pubDate>
		<dc:creator>Jettro Coenradie</dc:creator>
				<category><![CDATA[Frontend Technology]]></category>
		<category><![CDATA[groovy and grails]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[elasticsearch]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1858</guid>
		<description><![CDATA[<p><p> <p>In my previous blog posts I was working on reading data from wordpress blogs using groovy. This is nice, but of course there was a reason why I needed this. I wanted to create a tool or better a plugin for Elasticsearch. This plugin should make it easier to check the state of you [...]</p><p>The post <a href="http://www.gridshore.nl/2013/03/12/introducing-a-query-tool-for-elasticsearch/">Introducing a query tool for elasticsearch</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></description>
				<content:encoded><![CDATA[<p><img src="http://www.gridshore.nl/wp-content/uploads/es.png" alt="ElasticSearch logo" border="0" width="200" height="62" style="float:right;" />
<p>In my previous blog posts I was working on reading data from wordpress blogs using groovy. This is nice, but of course there was a reason why I needed this. I wanted to create a tool or better a plugin for Elasticsearch. This plugin should make it easier to check the state of you cluster, play around with facets and query your data.</p>
<p>On my employers blog I started a series of blog posts that explain this plugin. I go into details for the libraries I used: AngularJS, Twitter Bootstrap and of course elastic.js.</p>
<p>Check my employers blog post if you are interested.</p>
<p><a href="http://blog.trifork.com/2013/03/12/introducing-a-query-tool-as-an-elasticsearch-plugin-part-1/">Introducing a query tool as an elasticsearch plugin (part 1)/</a></p>
<p>The post <a href="http://www.gridshore.nl/2013/03/12/introducing-a-query-tool-for-elasticsearch/">Introducing a query tool for elasticsearch</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2013/03/12/introducing-a-query-tool-for-elasticsearch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Doing more ElasticSearch with groovy</title>
		<link>http://www.gridshore.nl/2013/01/31/doing-more-elasticsearch-with-groovy/</link>
		<comments>http://www.gridshore.nl/2013/01/31/doing-more-elasticsearch-with-groovy/#comments</comments>
		<pubDate>Thu, 31 Jan 2013 21:07:45 +0000</pubDate>
		<dc:creator>Jettro Coenradie</dc:creator>
				<category><![CDATA[groovy and grails]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[elasticsearch]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1845</guid>
		<description><![CDATA[<p><p>In my previous blog post I wrote about a groovy client for reading a wordpress blog. Than using this client I send the data to ElasticSearch to be indexed. Of course you cannot do anything with ElasticSearch if you do not read the data by executing queries. So that blog post also talks about executing [...]</p><p>The post <a href="http://www.gridshore.nl/2013/01/31/doing-more-elasticsearch-with-groovy/">Doing more ElasticSearch with groovy</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>In my previous blog post I wrote about a groovy client for reading a wordpress blog. Than using this client I send the data to ElasticSearch to be indexed. Of course you cannot do anything with ElasticSearch if you do not read the data by executing queries. So that blog post also talks about executing search queries and doing count queries.</p>
<p>But what if you want to start playing with things like facets? What if we want to use a different analyzer to separate the keywords on a comma? Than you can use curl. No wait there is more. You can also use groovy of course.</p>
<p>That is what I discuss in this blog post, creating and removing indexes. Beware, this is not something you want to do on your production server. Deleting an index makes the index disappear, yes for real, you cannot get it back.</p>
<p>Read on if you want to learn more about groovy and ElasticSearch.</p>
<p><span id="more-1845"></span><br />
<h2>Prequel</h2>
<p>Please read my previous post if you want to understand the sample that I am creating. I will not discuss it in this blog post.</p>
<p><a href="http://www.gridshore.nl/2013/01/27/learning-about-elasticsearch/">Learning about ElasticSearch/</a></p>
<h2>Delete an index</h2>
<p>Again be careful, usually this is not possible in production. You should disable it.</p>
<p>The ElasticSearchGateway contains the following method to delete an index.</p>
<pre class="brush: groovy; title: ; notranslate">
public deleteIndex() {
    try {
        def response = node.client.admin.indices.prepareDelete(indexValue).execute().get()
        if (response.acknowledged) {
            println &quot;The index is removed&quot;
        } else {
            println &quot;The index could not be removed&quot;
        }
    } catch (Exception e) {
        println &quot;The index you want to delete is missing : ${e.message}&quot;
    }
}
</pre>
<p>node is an instance of GNode created in the constructor of my Gateway class. You ask for the client to get access to the ElasticSearch cluster. Than ask for the admin part on which you can call index related queries. In this case we call the prepareDelete method. I put a try-catch around the delete statement. I do not want the script to stop if the index cannot be deleted because it is not there.</p>
<h2>Creating the index</h2>
<p>Before I show you have to create an index with some advanced stuff going on in there, I want to explain why I needed it. I want to create facets around the keywords and the categories in my blogs. The format of the keywords field is:</p>
<pre>
Yvonne van der Mey, fotografie, bloemen
</pre>
<p>I want three terms out of this after analyzing for creating facets. Therefore I want to tokenize based on the comma and I want to strip the spaces from the items. This can be done with a custom analyzer. The custom analyzer refers to a pattern based tokenizer and a trimming filter. In groovy you can create this index, with settings and mappings as shown in the next block.</p>
<pre class="brush: groovy; title: ; notranslate">
public createIndex() {
    def future = node.client.admin.indices.create {
        index = this.indexValue
        settings {
            number_of_shards = &quot;1&quot;
            analysis {
                analyzer {
                    comma {
                        type = &quot;custome&quot;
                        tokenizer = &quot;bycomma&quot;
                        filter = [&quot;nowhite&quot;]
                    }
                }
                tokenizer {
                    bycomma {
                        type = &quot;pattern&quot;
                        pattern = &quot;,&quot;
                    }
                }
                filter {
                    nowhite {
                        type = &quot;trim&quot;
                    }
                }
            }
        }
        mapping this.typeValue, {
            &quot;${this.typeValue}&quot; {
                properties {
                    keywords {
                        type = &quot;string&quot;
                        analyzer = &quot;comma&quot;
                    }
                    categories {
                        type = &quot;string&quot;
                        analyzer = &quot;comma&quot;
                    }
                }
            }
        }
    }

    future.success = { CreateIndexResponse response -&gt;
        println &quot;Index is created&quot;
    }

    future.failure = {
        println &quot;ERROR creating index $it&quot;
    }

}
</pre>
<p>With groovy you can use the closure notation to create these items like settings and mappings. This way the method with a string containing the source is called and the closure is transformed into the json structure. The notation looks very similar to the json as provided when using curl.</p>
<p>A nice way to test if your analyzer works is using curl. You can actually call the analyzer with a string to be analyzed.</p>
<pre>
[~]$ curl -XGET 'localhost:9200/coenradie/_analyze?analyzer=comma&#038;pretty=true' -d 'this ,is a ,test, with a lot of,difference,'
{
  "tokens" : [ {
    "token" : "this",
    "start_offset" : 0,
    "end_offset" : 5,
    "type" : "word",
    "position" : 1
  }, {
    "token" : "is a",
    "start_offset" : 6,
    "end_offset" : 11,
    "type" : "word",
    "position" : 2
  }, {
    "token" : "test",
    "start_offset" : 12,
    "end_offset" : 16,
    "type" : "word",
    "position" : 3
  }, {
    "token" : "with a lot of",
    "start_offset" : 17,
    "end_offset" : 31,
    "type" : "word",
    "position" : 4
  }, {
    "token" : "difference",
    "start_offset" : 32,
    "end_offset" : 42,
    "type" : "word",
    "position" : 5
  } ]
}
</pre>
<p>As you can see, the spaces at the end and beginning are removed, but we have multiple words as one token. Exactly like I want.</p>
<p>The code also shows we use this analyzer for two fields: keywords and categories. The next screen shows another project I am working on. This project is actually the main project but I needed some content so I created the groovy scripts to find content and send them to ElasticSearch. Check the facets at the bottom of the screen.</p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/Screen-Shot-2013-01-31-at-22.03.28.png" alt="Screen Shot 2013 01 31 at 22 03 28" border="0" width="600" height="329" /></p>
<p>I hop you like this addition. My next blog will be about ElasticSearch and writing a plugin using AngularJS.</p>
<p>The post <a href="http://www.gridshore.nl/2013/01/31/doing-more-elasticsearch-with-groovy/">Doing more ElasticSearch with groovy</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2013/01/31/doing-more-elasticsearch-with-groovy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Learning about ElasticSearch</title>
		<link>http://www.gridshore.nl/2013/01/27/learning-about-elasticsearch/</link>
		<comments>http://www.gridshore.nl/2013/01/27/learning-about-elasticsearch/#comments</comments>
		<pubDate>Sun, 27 Jan 2013 09:04:53 +0000</pubDate>
		<dc:creator>Jettro Coenradie</dc:creator>
				<category><![CDATA[groovy and grails]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[elasticsearch]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1841</guid>
		<description><![CDATA[<p><p> <p>This week I had a training at Trifork Amsterdam by Martijn and Uri from ElasticSearch. This training was a very nice in depth look at the capabilities of ElasticSearch. Like with all trainings and conferences I get motivated to try out the technology immediately. I am working on a plugin for ElasticSearch using AngularJS. [...]</p><p>The post <a href="http://www.gridshore.nl/2013/01/27/learning-about-elasticsearch/">Learning about ElasticSearch</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></description>
				<content:encoded><![CDATA[<p><img src="http://www.gridshore.nl/wp-content/uploads/es.png" alt="ElasticSearch logo" border="0" width="200" height="62" style="float:left;" />
<p>This week I had a training at <a href="http://www.trifork.nl">Trifork</a> Amsterdam by Martijn and Uri from <a href="http://www.elasticsearch.org">ElasticSearch</a>. This training was a very nice in depth look at the capabilities of ElasticSearch. Like with all trainings and conferences I get motivated to try out the technology immediately. I am working on a plugin for ElasticSearch using AngularJS. More on this in a next <a href="http://blog.trifork.nl">blog at Trifork</a>.</p>
<p>In this blog I am going to tell you the steps I took to get going with ElasticSearch. I show some of the steps for installing ElasticSearch, explain the first steps in using the groovy library. Next to that I&#8217;ll show you how to index this wordpress blog using ElasticSearch. When everything is indexed I will of course show some of the queries you can perform.</p>
<p>Let us get going.</p>
<p><span id="more-1841"></span><br />
<h2>Installing and configuring</h2>
<p>I do not want to make this part to extensive. The documentation at the site of ElasticSearch is rigorous and therefore my extra lines would be to much. Some of the things I want to accomplish in the configuration are:</p>
<ul>
<li>Start elastic search with the logs in your command prompt: -f</li>
<li>Specify the location of the configuration file: -Des.config=/path/to/config/file</li>
<ul>
<li>Change the name of the cluster and the node: cluster.name: jc-elasticsearch and node.name: &#8220;Node-gridshore&#8221;</li>
<li>Disable the multiple shards and replicas for local development: index.number_of_shards: 1 and index.number_of_replicas: 0</li>
<li>Path to the location of the configuration files: path.conf: /path/to/conf</li>
<li>Other paths, like work folder, logs folder, data folder and plugin folder.</li>
</ul>
<li>Install the head plugin to have a look at whay is happening to your cluster. I have chosen to install the plugin in the normal directory and than copy it to my configured plugins folder.</li>
</ul>
<p>Don&#8217;t forget to install and use java 7, al that java 6 stuff is really old and slow compared to 7. ElasticSearch can do a better job when running on 7.</p>
<p>Those are the first commands to get everything running, so once more the steps:</p>
<ol>
<li>Download elastic search: <a href="http://www.elasticsearch.org/download/">http://www.elasticsearch.org/download/</a>. I used 0.20.2</li>
<li>Create a directory structure outside of the downloaded elastic search folder: config, data, logs, plugins, work.</li>
<li>Copy the elastic search.yml and logging.yml to the config folder and make the changes as mentioned.</li>
<li>Install the plugin and copy it to your plugins folder: bin/plugin -install Aconex/elasticsearch-head</li>
<li>Move to the main folder of you ElasticSearch download and execute the command (with your location of the config file)</li>
</ol>
<pre>
bin/elasticsearch -f -Des.config=/.../elasticsearch/projects/gridshore/config/elasticsearch.yml
</pre>
<p>Now you can browse to the head plugin and see that not a lot has happened yet.</p>
<p><a href="http://localhost:9200/_plugin/head/index.html">http://localhost:9200/_plugin/head/index.html</a></p>
<p>Before going to the index creation you can play around with some aspects of the REST api that ElasticSearch exposes: Try a few of these requests with curl to see the data that ElasticSearch exposes. Don&#8217;t use the pretty=true in production.</p>
<p><a href="http://localhost:9200/_cluster/state?pretty=true">http://localhost:9200/_cluster/state?pretty=true</a><br/><br />
<a href="http://localhost:9200/_cluster/nodes?pretty=true">http://localhost:9200/_cluster/nodes?pretty=true</a><br/></p>
<h2>Reading the data using Groovy</h2>
<p>Of course you can create the index and the required mapping using the curl based api. You can also just insert a document and the index will be created automatically and the default mapping will be created. In our case I first want to introduce you to the groovy client I use to read data from the blog using xmlrpc and the data model. Than we move on to the mapping.</p>
<p>In the sample code I use gradle to configure the project and my environment (Intellij).</p>
<pre class="brush: groovy; title: ; notranslate">
dependencies {
	groovy 'org.codehaus.groovy:groovy:2.0.6'
    groovy 'org.codehaus.groovy:groovy-all:2.0.6'
    groovy ('org.codehaus.groovy:groovy-xmlrpc:0.8') {
        exclude module: 'groovy-all'
    }
    groovy 'commons-cli:commons-cli:1.2'
    groovy 'log4j:log4j:1.2.16'

    groovy ('org.elasticsearch:elasticsearch-lang-groovy:1.2.0') {
        exclude module: 'groovy-all'
    }
}
</pre>
<p>There is some strange thing going on with the groovy and groovy-all libraries. But I had some issues combining intellij and gradle. This seems to work for me. Notice that we need the groovy-xmlrpc library and of course the elasticsearch-lang-groovy library.</p>
<p>Using the following groovy class we can read all posts from the gridshore blog. Since the code is straightforward, I am not going in any details.</p>
<pre class="brush: groovy; title: ; notranslate">
package nl.gridshore.wordpress

import groovy.net.xmlrpc.XMLRPCServerProxy

class WordPressReader {
    private String xmlrpcUrl
    private String username
    private String password

    private XMLRPCServerProxy serverProxy;

    def WordPressReader(xmlrpcUrl, username, password) {
        this.xmlrpcUrl = xmlrpcUrl
        this.username = username
        this.password = password

        serverProxy = new XMLRPCServerProxy(xmlrpcUrl)
        serverProxy.setBasicAuth(username, password)
    }

    def obtainMostRecentPosts(int number = 10) {
        def posts = []
        def foundPosts = serverProxy.metaWeblog.getRecentPosts(1, username, password, number)
        foundPosts.each {post -&gt;
            def blogItem = new BlogItem()
            blogItem.id = post['postid']
            blogItem.link = post['permaLink']
            blogItem.status = post['post_status']
            blogItem.keywords = post['mt_keywords']
            blogItem.title = post['title']
            blogItem.createdOn = post['dateCreated']
            blogItem.content = post['description']
            blogItem.categories = post['categories']
            blogItem.author = post['wp_author_display_name']
            blogItem.slug = post['wp_slug']
            posts.add(blogItem)
        }
        return posts
    }
}
</pre>
<p>Time to put some stuff into ElasticSearch</p>
<h2>Put some data into the index</h2>
<p>The groovy library is very easy to use. The following code block shows the opening and closing of the connection. We make use of a client node that does not contain data. Take special notice of the line where we set a property for GXContentBuilder, this is required to enable the configuration using a closure. In the constructor we open the connection and in you have to close the connection using the close method.</p>
<pre class="brush: groovy; title: ; notranslate">
package nl.gridshore.elasticsearch

import nl.gridshore.wordpress.BlogItem
import org.elasticsearch.action.index.IndexResponse
import org.elasticsearch.groovy.common.xcontent.GXContentBuilder
import org.elasticsearch.groovy.node.GNode
import org.elasticsearch.groovy.node.GNodeBuilder

import static org.elasticsearch.groovy.node.GNodeBuilder.nodeBuilder

class ElasticSearchGateway {
    GNode node

    ElasticSearchGateway() {
        GXContentBuilder.rootResolveStrategy = Closure.DELEGATE_FIRST; // required to use a closure as settings

        GNodeBuilder nodeBuilder = nodeBuilder();
        nodeBuilder.settings {
            node {
                client = true
            }

            cluster {
                name = &quot;jc-elasticsearch&quot;
            }
        }

        node = nodeBuilder.node()
    }

    public close() {
        node.stop().close()
    }
}
</pre>
<p>Now that we know how to obtain a connection, let us obtain some data and store the documents in the ElasticSearch index. The next method is also coming from the ElasticSearchGateway class that I have created. This is the most basic version that auto creates and index and the complete mapping.</p>
<pre class="brush: groovy; title: ; notranslate">
    public indexBlogItem(BlogItem blogItem) {
        def future = node.client.index {
            index = &quot;gridshore&quot;
            type = &quot;blog&quot;
            source {
                blogId = blogItem.id
                link = blogItem.link
                status = blogItem.status
                keywords = blogItem.keywords
                title = blogItem.title
                createdOn_date = blogItem.createdOn
                content = blogItem.content
                categories = blogItem.categories
                author = blogItem.author
                slug = blogItem.slug
            }
        }

        future.success = {IndexResponse response -&gt;
            println &quot;Indexed $response.index/$response.type/$response.id&quot;
        }
    }
</pre>
<p>With the following script we obtain 100 items from my blog and add them to the ElasticSearch index.</p>
<pre class="brush: groovy; title: ; notranslate">
import nl.gridshore.elasticsearch.ElasticSearchGateway
import nl.gridshore.wordpress.BlogItem
import nl.gridshore.wordpress.WordpressReader

def rpcUrl = &quot;http://www.gridshore.nl/xmlrpc.php&quot;
def username = &quot;?&quot;
def password = &quot;?&quot;

def reader = new WordPressReader(rpcUrl,username,password)

def posts = reader.obtainMostRecentPosts(100)

ElasticSearchGateway gateway = new ElasticSearchGateway()

posts.each {BlogItem item -&gt;
    println item.title
    gateway.indexBlogItem(item)
}

System.in.withReader {
    print 'input: '
    println it.readLine()
}

gateway.close()
</pre>
<h2>Execute queries on the data</h2>
<p>Now that I told you I have data in the index, let us create a query to check if there is actually something in the index. Of course we use groovy to query the index and to print the results.</p>
<pre class="brush: groovy; title: ; notranslate">
    public queryIndex(theTerm) {
        def search = node.client.search {
            indices : &quot;gridshore&quot;
            types : &quot;blog&quot;
            source {
                query {
                    term(_all: theTerm)
                }
            }
        }

        search.response.hits.each {SearchHit hit -&gt;
            println &quot;Got hit $hit.id from $hit.index/$hit.type with title $hit.source.title&quot;
        }
    }
</pre>
<p>By running the following script I get the shown results.</p>
<pre class="brush: groovy; title: ; notranslate">
import nl.gridshore.elasticsearch.ElasticSearchGateway

ElasticSearchGateway gateway = new ElasticSearchGateway()

gateway.queryIndex(&quot;groovy&quot;)

System.in.withReader {
    print 'input: '
    println it.readLine()
}

gateway.close()
</pre>
<pre>
Got hit Huib3BPiTEua7Yvy6kc83w from gridshore/blog with title Doing more with groovy
Got hit lp79gd1UQ6mSdp3yp7O8Jg from gridshore/blog with title Analyzing beet results with groovy
Got hit CoRdYwD9ScyNnocqDvLGYg from gridshore/blog with title Cleaning up your maven repository with groovy
Got hit _U2q3miSRn6dTdUJB9PNYA from gridshore/blog with title Cleaning up artifactory with a groovy script
Got hit StrcQtnwTJSIvlu0pYojpA from gridshore/blog with title Exposing jmx through jmxmp and reading the jmx data with groovy
Got hit iQz0QFtYT3af9-Rls4d8Zw from gridshore/blog with title Use Grails and Axon to create a CQRS application (part II)
Got hit fajgAgrgST6AnNwCeyyocA from gridshore/blog with title Recap of the year 2010
Got hit V6h65a_rQ2mOvpE-POTF4Q from gridshore/blog with title Use Grails and Axon to create a CQRS application (part I)
Got hit xdi2KN9zQf2JD8qdbhBmdQ from gridshore/blog with title Using the NOS open data API with the springframework and jackson
Got hit DOiahRyMS0KUbg9e6BQHpQ from gridshore/blog with title Doing grails, yes I like it
</pre>
<p>The last function I want to show is counting documents. The following code block shows how to count all documents in the gridshore index of type blog. Thinking about the input for the amount of blogitems we imported, the result should be obvious.</p>
<pre class="brush: groovy; title: ; notranslate">
    public countAllDocuments() {
        def count = node.client.count {
            indices : &quot;gridshore&quot;
            parameterTypes : &quot;blog&quot;
        }
        
        println &quot;Number of found blog items : $count.response.count&quot;
    }
</pre>
<pre>
Number of found blog items : 100
</pre>
<p>This is it, you can find the sources online @github. Check my GridshoreSamples project, in there you&#8217;ll find a small project called groovy-es-client.</p>
<p><a href="https://github.com/jettro/GridshoreSamples" title="GridshoreSamples">https://github.com/jettro/GridshoreSamples</a></p>
<p>The post <a href="http://www.gridshore.nl/2013/01/27/learning-about-elasticsearch/">Learning about ElasticSearch</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2013/01/27/learning-about-elasticsearch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Review of the book: Presentation Patterns</title>
		<link>http://www.gridshore.nl/2012/12/30/review-of-the-book-presentation-patterns/</link>
		<comments>http://www.gridshore.nl/2012/12/30/review-of-the-book-presentation-patterns/#comments</comments>
		<pubDate>Sun, 30 Dec 2012 12:10:06 +0000</pubDate>
		<dc:creator>Jettro Coenradie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bookreview]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1835</guid>
		<description><![CDATA[<p><p>I have written a review about the book Presentation Patterns: Techniques for Crafting Better Presentations (@Amazon)</p> <p>In the past I have read multiple books about creating and giving presentations. I really like to present something to the public. On numerous NLJug events I have presented as well as a lot of internal events @ trifork.</p> [...]</p><p>The post <a href="http://www.gridshore.nl/2012/12/30/review-of-the-book-presentation-patterns/">Review of the book: Presentation Patterns</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>I have <a href="http://www.gridshore.nl/book-reviews/presentation-patterns/">written a review</a> about the book <a href="http://www.amazon.com/gp/product/0321820800/ref=as_li_qf_sp_asin_tl?ie=UTF8&#038;tag=gridshore-20&#038;linkCode=as2&#038;camp=1789&#038;creative=9325&#038;creativeASIN=0321820800">Presentation Patterns: Techniques for Crafting Better Presentations (@Amazon)</a><img src="http://www.assoc-amazon.com/e/ir?t=gridshore-20&#038;l=as2&#038;o=1&#038;a=0321820800" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></p>
<p>In the past I have read multiple books about creating and giving presentations. I really like to present something to the public. On numerous NLJug events I have presented as well as a lot of internal events @ trifork.</p>
<p>These books have helped me to improve my presentation skills as well as the process to come up with nice presentations.</p>
<p>If you are also interested in these kind of books and you do not mind that I earn a few bucks you can buy these books that I highly recommend @ Amazon.</p>
<table>
<tr>
<td>
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&#038;bc1=000000&#038;IS2=1&#038;nou=1&#038;bg1=FFFFFF&#038;fc1=000000&#038;lc1=0000FF&#038;t=gridshore-20&#038;o=1&#038;p=8&#038;l=as1&#038;m=amazon&#038;f=ifr&#038;ref=qf_sp_asin_til&#038;asins=0321820800" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</td>
<td>
<iframe src="http://rcm.amazon.com/e/cm?t=gridshore-20&#038;o=1&#038;p=8&#038;l=as1&#038;asins=0321811984&#038;nou=1&#038;ref=qf_sp_asin_til&#038;fc1=000000&#038;IS2=1&#038;lt1=_blank&#038;m=amazon&#038;lc1=0000FF&#038;bc1=000000&#038;bg1=FFFFFF&#038;f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</td>
</tr>
</table>
<p>The post <a href="http://www.gridshore.nl/2012/12/30/review-of-the-book-presentation-patterns/">Review of the book: Presentation Patterns</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2012/12/30/review-of-the-book-presentation-patterns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>This was my 2012</title>
		<link>http://www.gridshore.nl/2012/12/28/this-was-my-2012/</link>
		<comments>http://www.gridshore.nl/2012/12/28/this-was-my-2012/#comments</comments>
		<pubDate>Fri, 28 Dec 2012 10:27:13 +0000</pubDate>
		<dc:creator>Jettro Coenradie</dc:creator>
				<category><![CDATA[Axon Framework]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[server technology]]></category>
		<category><![CDATA[overview]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1828</guid>
		<description><![CDATA[<p><p>It is almost the end of the year, we are getting ready for 2013. Therefore I want to look back at my 2012 as a software engineer. I want to look back at the blogs I have written, the presentations I have given, the books I read and the conferences I attended. This blog post [...]</p><p>The post <a href="http://www.gridshore.nl/2012/12/28/this-was-my-2012/">This was my 2012</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>It is almost the end of the year, we are getting ready for 2013. Therefore I want to look back at my 2012 as a software engineer. I want to look back at the blogs I have written, the presentations I have given, the books I read and the conferences I attended. This blog post will give a nice overview of my year and therefore a lot of links to the things I found interesting.</p>
<h2>Twitter</h2>
<p>I am not a very active user on twitter with @gridshore. I do twitter more with my personal account @jettroCoenradie. Still it is not hard to see what I was busy with this year. Check my <a href="https://www.vizify.com/gridshore/year-on-twitter">twitter overview created with vizify</a></p>
<h2>Presentations</h2>
<p>This year I presented at two events. At the Hippo Gettogether I presented about the ldap integration we did at the University of Amsterdam. You can find the slides here at <a href="http://www.slideshare.net/hippocms/hippo-ldapjettrocoenradie1">slideshare</a>.</p>
<p>At the yearly JFall conference of the NLJug i presented about <a href="http://www.nljug.org/pages/events/content/jfall_2012/sessions/00079/">creating polyglot and scalable applications</a>. You can download the slides, but you can also watch the <a href="http://www.parleys.com/#st=5&#038;id=3431&#038;sl=0">presentation on Parleys</a>.</p>
<h2>Blogs</h2>
<p>When looking back I see there is not a lot of activity on the gridshore website. Most of my activity moved to my employers blog. Therefore I have decided to write a short post in here as well when I write a blog post at my employers blog.</p>
<p>My year started with a blog post about <a href="http://blog.trifork.nl/2012/02/03/running-hippo-from-intellij/">running the hippo cmd components from within intellij</a>. At Hippo they preferred the cargo plugin to run their components, which is not ideal when debugging your software. Therefore I came up with a way to make it easy to run your components in intellij.</p>
<p>The next blogpost I wrote was about <a href="http://www.gridshore.nl/2012/02/28/a-mongodb-based-axon-framework-event-store/">creating a MongoDB based event store</a> for the Axonframework. Allard made some nice improvements to the event store, but this was the foundation. The event store is used in a sample application called the Axon Trader. More on this later on.</p>
<p>I am a hobbyist photographer. I attend a number of workshops every year at <a href="http://www.yvonnevandermey.nl">Yvonne van der Mey</a>. She needed a new website and I like to help people out. Therefore I created a wordpress based website for her. I have a number of other wordpress website under maintenance (www.wateenjuweeltje.nl, www.coenradie.com,www.nicobulder.com). In the beginning I was doing my editing  on the server, but I wanted to have a better solution. I started using git to have a history for my scripts. Manually copying the sources to the server was not nice. Therefore I created a few scripts to check git what changes were not send to the server yet. Using ftp I send these files to the server. Of course I wrote a blog post about this: <a href="http://www.gridshore.nl/2012/03/23/deployments-with-git-and-bash-on-a-mac/">Deployments with Git and Bash on a Mac</a>.</p>
<p>I continued building applications using Axonframework and MongoDB. I already created the event store, but an application using axon also has a query side. For the Axon Trader sample I wanted to use MongoDB for the query side as well. I heard about the spring-data project and thought there was a good match for my sample. In <a href="http://blog.trifork.nl/2012/03/29/using-the-spring-data-project-and-the-mongodb-adapter-specifically/">this blog post</a> I discussed my experiences with the spring-data project and the MongoDB module specifically.</p>
<p>For a number of projects we wanted information about the server using a ping request. I thought it was good to create something reusable, therefore I created the Healthcheck library. In this blogpost you can read more about the <a href="http://blog.trifork.nl/2012/04/19/basic-health-check-library-for-your-application/">java based health check library</a>.</p>
<p>For the University of Amsterdam we are creating a Hippo based solution for their new websites. Like with other hippo projects we have a lot of integration to do. I usually create an administrator application for managing all these integration components. Of course we do not want everybody to be able to login, therefore we have created an <a href="http://blog.trifork.nl/2012/07/17/authenticate-against-a-hippo-repository-using-spring-security/">authentication mechanism for Spring-security to authenticate against a hippo repository</a>. This blog post discusses that mechanism.</p>
<p>During 2012 I started learning about Vert.x. This is a very nice application framework to create scalable/polyglot applications on the JVM. I had an idea about a presentation proposal for the NLJuG JFall event. Before being able to present about it I had to learn. Usually I learn by creating sample applications and blogging about my experiences. Therefore I wrote this blog post about my <a href="http://www.gridshore.nl/2012/06/03/first-steps-with-vert-x-creating-a-websocket-sample/">first steps with vert.x</a>. This was a very well read blogpost that was tweeted about 32 times. Nice to know that people liked what I was doing.</p>
<p>During the Devoxx conference I learned about AngularJS. I really liked the idea around this JavaScript framework. It also seemed easy enough to work with. With my interest in Vert.x and Axonframework I wanted to combine this knowledge in a sample application. This blog post described my experiences: <a href="http://blog.trifork.nl/2012/11/27/basic-axon-framework-sample-using-vert-x-and-angular-js/">Basic Axon Framework sample using vert.x and angular.js</a>.</p>
<h2>Conferences</h2>
<p>In May I attended the GoTo conference in Amsterdam. At Trifork we organise all the GoTo conferences. The one in Amsterdam was a nice conference this year. I learned a lot and got <a href="http://blog.trifork.nl/2012/05/30/getting-inspired-by-goto-amsterdam/"> really inspired by a few talks</a>.</p>
<p>In November I was able to join the Devoxx conference. What I thrill this is. I attended a lot of presentations and we joined a booth with 10gen, the creators of MongoDB. I had some very interesting talks that made me think and want to try out new stuff. I really liked the talk about AngularJS. The evening I got back I rewrote a part of a sample using angularJS. This is really something for the future. Here you can read more about <a href="http://blog.trifork.nl/2012/11/17/and-that-was-devoxx-2012-partnering-with-10gen-and-a-lot-of-knowledge-gaining/">my devoxx 2012</a>.</p>
<h2>iOS</h2>
<p><img src="http://www.gridshore.nl/wp-content/uploads/screen-ios-rekenen.png" alt="Screen ios rekenen" title="screen-ios-rekenen.png" border="0" width="320" height="480" style="float:right;" /></p>
<p>In this year I also started learning about iOS development. I started with an app for the iPad. But since both my kids have an iPod touch I wanted to create a very basic application to learn mathematics for the kids. I&#8217;ll write more about this in 2013.</p>
<h2>Books</h2>
<p>Like every year I spend some money on books. A lot of them are eBooks, but I also keep buying hard copy books.</p>
<ul>
<li>Presentation patterns &#8211; Neal Ford</li>
<li>The lean startup &#8211; Eric Ries</li>
<li>Just enough software architecture &#8211; George Fairbanks</li>
<li>Java Performance &#8211; Charlie Hunt</li>
<li>Don&#8217;t make me think &#8211; Steve Krug</li>
<li>Spring Integration in Action &#8211; Mark Fisher</li>
<li>7 databases in 7 weeks &#8211; Eric Redmond</li>
<li>iOS Storyboarding &#8211; Dr. Rory Lewis</li>
<li>The iOS 5 developers Cookbook &#8211; Erica Sadun</li>
<li>iOS SDK Development &#8211; Chris Adamson</li>
</ul>
<p>The post <a href="http://www.gridshore.nl/2012/12/28/this-was-my-2012/">This was my 2012</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2012/12/28/this-was-my-2012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why should I want that?</title>
		<link>http://www.gridshore.nl/2012/10/17/why-should-i-want-that/</link>
		<comments>http://www.gridshore.nl/2012/10/17/why-should-i-want-that/#comments</comments>
		<pubDate>Wed, 17 Oct 2012 13:22:54 +0000</pubDate>
		<dc:creator>Jettro Coenradie</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1821</guid>
		<description><![CDATA[<p><p>I have two sons that I try to raise to become nice boys with a good education while having a lot of fun. In the evening I tell them to take a shower, brush their teeth. During the day I tell them to listen well, be nice to their mother and to each other. Still [...]</p><p>The post <a href="http://www.gridshore.nl/2012/10/17/why-should-i-want-that/">Why should I want that?</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>I have two sons that I try to raise to become nice boys with a good education while having a lot of fun. In the evening I tell them to take a shower, brush their teeth. During the day I tell them to listen well, be nice to their mother and to each other. Still they regularly they respond that they do not want to do something like cleaning their room, or finish their diner before getting a desert. I am glad they do not respond yet with &#8220;Why should I want that?&#8221;.</p>
<p>Both my sons play soccer. I am one of those fathers that played soccer themselves and therefore think they are qualified to be a soccer trainer. Well, someone needs to do it and the kids and parent tell me I do a good job. Of course I did some research on the internet, watched youtube movies and I even attended a &#8220;train the trainer training&#8221; (nice sentence). When training the kids (around 10 of them) I ask them to try certain exercises like tip the ball with your toe, pass the ball to someone else and wait to get it back. I think you get the idea. During the training I try to combine hard work with having fun. Still the first thing the kids ask is: when are we going to play a match? However, when explaining a new exercise, I am glad they do not ask &#8220;Why should I want that?&#8221;.</p>
<p>At work I am one of the seniors of the company. I like to mentor/coach my colleagues. I think it is great to see interns grow from still in school &#8220;I know the world guys&#8221; into men who have actually been part of something. I like to think about the future together with them, and make plans. Talk about what they want to become and the steps they need to take. I discuss the questions they need to ask themselves. I think it is very important to like what you are doing at work. It is hard to keep up if you are not having fun. One thing that surprises me is that colleagues very often forget to ask the question &#8220;Why should I want that?&#8221;</p>
<p>The post <a href="http://www.gridshore.nl/2012/10/17/why-should-i-want-that/">Why should I want that?</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2012/10/17/why-should-i-want-that/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>First steps with vert.x: creating a WebSocket sample</title>
		<link>http://www.gridshore.nl/2012/06/03/first-steps-with-vert-x-creating-a-websocket-sample/</link>
		<comments>http://www.gridshore.nl/2012/06/03/first-steps-with-vert-x-creating-a-websocket-sample/#comments</comments>
		<pubDate>Sun, 03 Jun 2012 06:43:32 +0000</pubDate>
		<dc:creator>Jettro Coenradie</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[axonframework]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[sockjs]]></category>
		<category><![CDATA[vert.x]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1235</guid>
		<description><![CDATA[<p><p>Some time a go, a colleague of mine (Joris) told me about vert.x. I liked the idea of having something like node.js on the java platform. So I was interested, but I did not spend time on it. Recently I attended the talk of Tim Fox at the Goto conference in Amsterdam. Again I liked [...]</p><p>The post <a href="http://www.gridshore.nl/2012/06/03/first-steps-with-vert-x-creating-a-websocket-sample/">First steps with vert.x: creating a WebSocket sample</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></description>
				<content:encoded><![CDATA[<p>Some time a go, a colleague of mine (Joris) told me about vert.x. I liked the idea of having something like node.js on the java platform. So I was interested, but I did not spend time on it. Recently I attended the talk of Tim Fox at the <a href="http://gotocon.com/amsterdam-2012">Goto conference in Amsterdam</a>. Again I liked the idea about vert.x. Therefore I decided to give it a go.</p>
<p>For the axon trader sample I am working on I want to have a screen of executed trades. I want the screen to be updated as soon as possible. I have some wild ideas of connecting the vert.x event bus to the axon event bus, but that is not the focus for this blog post. In this blog post I am going to step through the stages of creating a sample vert.x application that makes use of sockjs to visit a page where you can connect to the event system and get updates about the executed trades. The executed trades are stored in a MongoDB instance. I use the query tables from the axon-trader sample, but this is not a requirement for you to replay the sample.</p>
<p>I am also not going to explain what vert.x is, the website <a href="http://vertx.io/">http://vertx.io/</a> does a good job already. Expect a lot of code samples and of course the source is available in github. Check the references at the end.</p>
<p>If you are still interested, the click the read more link and start reading. Feedback and improvements are appreciated.</p>
<p><span id="more-1235"></span></p>
<h2>Create a web app</h2>
<p>We start of creating a very basic web application. No static files, no ajax, no web2.0. Just a request and a response. The following code block shows you how to create a web server serving three urls: /trades, /orders/buy and /orders/sell. I also wanted to create a request nog found page, but this was not working in my current code base using groovy.</p>
<pre class="brush: groovy; title: ; notranslate">
def server = vertx.createHttpServer()
def routeMatcher = new RouteMatcher()
routeMatcher.get(&quot;/trades&quot;) {req -&gt;
    req.response.end &quot;You requested trades&quot;
}
routeMatcher.get(&quot;/orders/:type&quot;) {req -&gt;
    def type = req.params[&quot;type&quot;]
    if (type == &quot;sell&quot;)
        req.response.end &quot;You requested buy orders&quot;
    else if (type == &quot;buy&quot;)
        req.response.end &quot;You requested sell orders&quot;
    else
        req.response.end &quot;You requested orders of unknown type&quot;
}
server.requestHandler(routeMatcher.asClosure()).listen(8080, &quot;localhost&quot;)
</pre>
<p>As you can see we need to create the http server and a Routematcher. Then we specify the routes to match. The trades is very easy and the orders are a little bit more complicated using a query parameter, but you should be able to understand this as well. The final registers the handler for the event of receiving a request and initializes the listener using the server name and the port.</p>
<p>Next step is obtaining data from mongoDB using the provided mongodb BusMod.</p>
<h2>Attach the web app to mongodb</h2>
<p>In the nature of vert.x and using events, we use the event bus to send a message to mongo and receive the reply in a callback. But before we can send a message, we need to initialize the mongo verticle. The next code block shows setting up the mongodb vertical using the defaults for address,host and port. The address is interesting, this is the address in the event bus that the mongodb persistence verticle listens for incoming requests. This default is <strong>vertx.mongopersistor</strong>. As you can see we use the mongo database for the axon trader. See references for more information about this sample.</p>
<pre class="brush: groovy; title: ; notranslate">
def mongoConfig = [&quot;db_name&quot;:&quot;axontrader&quot;]
container.with {
    deployVerticle('mongo-persistor', mongoConfig)
}
</pre>
<p>Before we can send messages to the event bus, we need to have a reference to the event bus. This is easy to obtain.</p>
<pre class="brush: groovy; title: ; notranslate">
def eventBus = vertx.eventBus
</pre>
<p>Now we can send messages. I already mentioned the address to send the messages to. When sending a message to obtain data you need to provide the collection to read the data from and a matcher to filter the items that you need. I had some problems finding the right format for the query (see the problems section). You also want to provide a callback that receives the data that was found. The next code block shows how we return data back to the client that was found in mongo.</p>
<pre class="brush: groovy; title: ; notranslate">
routeMatcher.get(&quot;/trades&quot;) {req -&gt;
    def query = [&quot;action&quot;:&quot;find&quot;,&quot;collection&quot;:&quot;tradeExecutedEntry&quot;,&quot;matcher&quot;:[:]]
    eventBus.send(&quot;vertx.mongopersistor&quot;,query) {message -&gt;
        req.response.end &quot;The following trades were found: ${message.body}&quot;
    }
}
</pre>
<p>Have a look at the query where we specify the action, the collection and the matcher. There are other options, check the manual for them. The result is a message. The message contains the found data in the body. Also notice the used address for sending the message to using the event bus.</p>
<p>Since we want a human readable website, we cannot show a string containing json. Therefore we also want to have a better looking front end.</p>
<h2>Create a client that shows the data</h2>
<p>Creating a nice website involves providing access to some static files. Think about style sheets, javascripts and images. Of course vert.x has support for this. Vert.x comes with a verticle for serving static content. This is the WebServer. A nice functionality of this module is that you can use a bridge. This way the clients can send requests to the event bus immediately. A nice functionality, but I want to show another mechanism. I want to combine static resources with dynamic resources. This is not possible with the WebServer. There is no integration between the WebServer and the RouteMatcher. Therefore I have written a few functions. We start we the functions that handle the request for static resources. All resources are located in the static folder. The following two functions return the index.html and content requested starting with /static. These are actual files on the file system and also treated that way using the sendFile function.</p>
<pre class="brush: groovy; title: ; notranslate">
routeMatcher.get(&quot;/&quot;) { req -&gt;
    req.response.sendFile(&quot;traderclient/static/index.html&quot;)
}
routeMatcher.getWithRegEx(&quot;^\\/static\\/.*&quot;) { req -&gt;
    req.response.sendFile(&quot;traderclient/&quot; + req.path.substring(1))
}
</pre>
<p>Notice the way we use <strong>getWithRegEx</strong> to map all static content paths to the requested files that start with /static/.</p>
<p>The next step is more interesting. How to we render a webpage with the obtained executed trades. The next code block shows the new function.</p>
<pre class="brush: groovy; title: ; notranslate">
routeMatcher.get(&quot;/trades&quot;) {req -&gt;
    def query = [&quot;action&quot;:&quot;find&quot;,&quot;collection&quot;:&quot;tradeExecutedEntry&quot;,&quot;matcher&quot;:[:]]
    eventBus.send(&quot;vertx.mongopersistor&quot;,query) {message -&gt;
        def buffer = new Buffer();
        buffer.appendBytes(new File('traderclient/header.tpl').readBytes())

        buffer.appendString(&quot;&lt;table class='table table-striped'&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Company&lt;/th&gt;&lt;th&gt;amount&lt;/th&gt;&lt;th&gt;prize&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&quot;)
        def results = message.body.results
        results.each { item -&gt;
            buffer.appendString(&quot;&lt;tr&gt;&lt;td&gt;${item.companyName}&lt;/td&gt;&lt;td&gt;${item.tradeCount}&lt;/td&gt;&lt;td&gt;${item.tradePrice}&lt;/td&gt;&lt;/tr&gt;&quot;)
        }
        buffer.appendString(&quot;&lt;/tbody&gt;&lt;/table&gt;&quot;)

        buffer.appendBytes(new File('traderclient/footer.tpl').readBytes())
        req.response.end buffer
    }
}
</pre>
<p>First we create the buffer object and store the header.tpl file in it followed by the table with the items and the footer.tpl. As you can see this is a lot of text for creating a nice looking page.</p>
<p>A big disadvantage is that the server now generates the html, the browser is a lot better in doing this. Therefore I want to take the next step and use the WebSocket technology to render pages.</p>
<h2>Use WebSockets to send data to the browser</h2>
<p>Since WebSockets are not yet supported by all browsers, vert.x has support for the socks library. The framework facilitates creating a socks server that is connected to the HttpServer. We start we a clean groovy script. The following code block shows the initialization of the HttpServer together with a RouteMatcher that takes care of the static content.</p>
<pre class="brush: groovy; title: ; notranslate">
def server = vertx.createHttpServer()
def routeMatcher = new RouteMatcher()

routeMatcher.get(&quot;/&quot;) { req -&gt;
    req.response.sendFile(&quot;traderclient/static/socketDemo.html&quot;)
}

routeMatcher.getWithRegEx(&quot;^\\/static\\/.*&quot;) { req -&gt;
    req.response.sendFile(&quot;traderclient/&quot; + req.path.substring(1))
}

server.requestHandler(routeMatcher.asClosure())
</pre>
<p>This code has been discussed before. The next part is initializing the Sockjs server. This can be done very easily.</p>
<pre class="brush: groovy; title: ; notranslate">
vertx.createSockJSServer(server).bridge(prefix: '/eventbus', [[:]])
server.listen(9090)
</pre>
<p>The next part on the server is to periodically check the mongo datastore for trades and send these trades to registered listeners.</p>
<pre class="brush: groovy; title: ; notranslate">
EventBus eb = vertx.eventBus
vertx.setPeriodic(1000l) {
    def query = [&quot;action&quot;: &quot;find&quot;, &quot;collection&quot;: &quot;tradeExecutedEntry&quot;, &quot;matcher&quot;: [:]]

    eb.send(&quot;vertx.mongopersistor&quot;, query) {message -&gt;
        eb.send(&quot;updates.trades&quot;, message.body)
    }
}
</pre>
<p>As you can see, vert.x comes with a function to periodically do something. With these lines we call the mongo persisters via the event bus. The callback calls the even but again and send the data to the address <strong>updates.trades</strong>. This address is important for the client that needs to register a subscriber.</p>
<p>Now we can move on to the client. I am not going to show the complete page. Refer to the sources later on. The next code block shows the javascript code required to open the connection using sockjs and to subscribe to an address. The subscriber also defines the callback to use when a message is received.</p>
<pre class="brush: jscript; title: ; notranslate">
    var eb = null;

    function subscribe() {
        if (eb) {
            eb.registerHandler(&quot;updates.trades&quot;, function (msg, replyTo) {
                var results = msg.results;
                $('#tradesBody').text('');
                for (var i = 0; i &lt; results.length; i++) {
                    var item = results[i];
                    $('#tradesBody').append(&quot;&lt;tr&gt;&lt;td&gt;&quot; + item.companyName + &quot;&lt;/td&gt;&lt;td&gt;&quot; + item.tradeCount + &quot;&lt;/td&gt;&lt;td&gt;&quot; + item.tradePrice + &quot;&lt;/td&gt;&lt;/tr&gt;&quot;);
                }
                $('#lastUpdate').text(&quot; &quot; + new Date());
            });
        }
    }

    function closeConn() {
        if (eb) {
            eb.close();
        }
    }

    function openConn() {
        if (!eb) {
            eb = new vertx.EventBus(&quot;http://localhost:9090/eventbus&quot;);

            eb.onopen = function () {
                $(&quot;#connectionStatus&quot;).text(&quot;Connected&quot;);
                subscribe();
            };

            eb.onclose = function () {
                $(&quot;#connectionStatus&quot;).text(&quot;Not connected&quot;);
                eb = null;
            };
        }
    }

    $(document).ready(function () {
        $(&quot;#closeButton&quot;).click(function () {
            closeConn();
        });

        $(&quot;#connectButton&quot;).click(function () {
            openConn();
        });
    });
</pre>
<p>The openConn function creates a connection to the event bus at a certain url. We use jQuery to change the status to connected and Not connected. We also call the subscribe function to subscribe to the trades.updates address. The subscribe function registers a handler for receiving a message on the mentioned address. The callback receives the results. Within the callback we loop over the results and using jQuery we replace the current contents of the table body.</p>
<p>Now we have a webpage that is being updated by the server when it is connected. The timer can be used to see things are changing. I use the mongodb collections from the Axon-Trader sample. In the nearby future I want to create an application with vert.x that responds to events coming from the axon event bus. But more on this in a future blog post.</p>
<p><img src="http://blog.orange11.nl/wp-content/uploads/2012/06/Screen-Shot-2012-06-01-at-14.16.54.png" alt="Screen Shot 2012 06 01 at 14 16 54" border="0" width="600" height="345" style="float:left;" /></p>
<h2>Problems during development</h2>
<pre>
Caused by: groovy.lang.MissingMethodException: No signature of method: org.vertx.java.core.http.RouteMatcher.noMatch() is applicable for argument types: (App$_run_closure3) values: [App$_run_closure3@77587f0]
Possible solutions: noMatch(org.vertx.java.core.Handler), patch(java.lang.String, org.vertx.java.core.Handler), each(groovy.lang.Closure)
</pre>
<p>Seems to be a problem that is already resolved in the master, but not in the current release. This error is found when trying to use the noMatch method of the RouteMatcher.</p>
<pre>
mei 31, 2012 10:00:48 AM org.vertx.java.core.logging.impl.JULLogDelegate error
SEVERE: matcher must be specified
[message:matcher must be specified, status:error]
</pre>
<p>The problem was an error in the query. You need to provide a matcher, but how to do it? The following line show the query with at the end the matcher that you must configure, even if you want to match everything.</p>
<pre>
def query = ["action":"find","collection":"tradeExecutedEntry","matcher":[:]]
</pre>
<h2>Concluding</h2>
<p>I really like what vert.x is doing. With very little code you can create a very responsive application. I really like the WebSocket and sockjs integration. The amount of modules are limited, but more will come in the nearby future. Check the references for more information about vert.x</p>
<h2>References</h2>
<ul>
<li><a href="http://vertx.io/docs.html">Manual(s) for vert.x</a></li>
<li><a href="https://github.com/AxonFramework/Axon-trader">AxonTrader sample</a></li>
<li><a href="https://github.com/jettro/vertx-samples">Sources of the sample</a></li>
<p> </ul>
<p>The post <a href="http://www.gridshore.nl/2012/06/03/first-steps-with-vert-x-creating-a-websocket-sample/">First steps with vert.x: creating a WebSocket sample</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2012/06/03/first-steps-with-vert-x-creating-a-websocket-sample/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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 Coenradie</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><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 [...]</p><p>The post <a href="http://www.gridshore.nl/2012/03/23/deployments-with-git-and-bash-on-a-mac/">Deployments with Git and Bash on a Mac</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></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>
<p>The post <a href="http://www.gridshore.nl/2012/03/23/deployments-with-git-and-bash-on-a-mac/">Deployments with Git and Bash on a Mac</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</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 Coenradie</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><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 post [...]</p><p>The post <a href="http://www.gridshore.nl/2012/02/28/a-mongodb-based-axon-framework-event-store/">A MongoDB based Axon framework event store</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</p>]]></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>
<p>The post <a href="http://www.gridshore.nl/2012/02/28/a-mongodb-based-axon-framework-event-store/">A MongoDB based Axon framework event store</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</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 Coenradie</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><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> </p><p>The post <a href="http://www.gridshore.nl/2011/12/13/creating-an-rss-feed-using-the-latest-features-of-hippo/">Creating an rss feed using the latest features of Hippo</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</a>.</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>
<p>The post <a href="http://www.gridshore.nl/2011/12/13/creating-an-rss-feed-using-the-latest-features-of-hippo/">Creating an rss feed using the latest features of Hippo</a> appeared first on <a href="http://www.gridshore.nl">Gridshore</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>
	</channel>
</rss>
