<?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>JTeam Blog</title>
	<atom:link href="http://blog.jteam.nl/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jteam.nl</link>
	<description>Keep updated on what we&#039;re doing!</description>
	<lastBuildDate>Tue, 02 Mar 2010 17:17:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Measuring code quality with Sonar</title>
		<link>http://blog.jteam.nl/2010/02/26/measuring-code-quality-with-sonar/</link>
		<comments>http://blog.jteam.nl/2010/02/26/measuring-code-quality-with-sonar/#comments</comments>
		<pubDate>Fri, 26 Feb 2010 12:13:38 +0000</pubDate>
		<dc:creator>Allard Buijze</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Quality]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=1856</guid>
		<description><![CDATA[ At JTeam, we continuously strive for good quality code. The reason is very simple: bad quality code slows down the development process. The small investment pays out in even the simplest of projects.
Measuring code quality is not a matter of a single metric. Instead, software quality has many aspects, some of which can be [...]]]></description>
			<content:encoded><![CDATA[<p><img style="margin: 0px 5px 5px 0px; display: inline; border-width: 0px;" title="sonar-blackonwhite" src="http://blog.jteam.nl/wp-content/uploads/2010/02/sonarblackonwhite.png" border="0" alt="sonar-blackonwhite" width="120" height="74" align="left" /> At JTeam, we continuously strive for good quality code. The reason is very simple: bad quality code slows down the development process. The small investment pays out in even the simplest of projects.</p>
<p>Measuring code quality is not a matter of a single metric. Instead, software quality has many aspects, some of which can be captured in metrics. Those metrics can be nicely assembled within a single application, which gives a nice overview of the state of an application: Sonar.</p>
<p><span id="more-1856"></span><a href="http://sonar.codehaus.org/" target="_blank">Sonar</a> (version 1.12 at the time of writing) is a web application that can be installed standalone or inside an existing Java Web Application Container, such as Tomcat. The standalone version is quite easy to install. Just download, start and a few moments later it’s ready on port 9000.</p>
<p>You can capture metrics using maven by running mvn sonar:sonar on your project. In some cases, your pom.xml file will need an explicit reference to this plugin, since it is not a default apache-maven plugin.</p>
<pre class="brush: xml;">&lt;build&gt;
  &lt;plugins&gt;
    &lt;plugin&gt;
      &lt;groupid&gt;org.codehaus.mojo&lt;/groupid&gt;
      &lt;artifactid&gt;sonar-maven-plugin&lt;/artifactid&gt;
    &lt;/plugin&gt;
  &lt;/plugins&gt;
&lt;/build&gt;</pre>
<p>After running mvn sonar:sonar on your project, Sonar will contain metrics information of your application. Browsing to &#8220;localhost:9000&#8243; will show this.</p>
<p>Sonar has a nice overview screen that shows certain metrics (you can configure which ones you want to see) for all project. In a software development organization, this means that you have a single point where you can measure each project’s “technical health”. You could even add custom metrics, such as budget, number of people on the project, number of story points left in the backlog, etc.</p>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/02/overview1.png"><img class="alignnone size-full wp-image-1875" title="overview" src="http://blog.jteam.nl/wp-content/uploads/2010/02/overview1.png" alt="" width="200" height="100" /></a> <a href="http://blog.jteam.nl/wp-content/uploads/2010/02/dashboard1.png"><img class="alignnone size-full wp-image-1873" title="dashboard" src="http://blog.jteam.nl/wp-content/uploads/2010/02/dashboard1.png" alt="" width="200" height="100" /></a> <a href="http://blog.jteam.nl/wp-content/uploads/2010/02/details1.png"><img class="alignnone size-full wp-image-1874" title="details" src="http://blog.jteam.nl/wp-content/uploads/2010/02/details1.png" alt="" width="200" height="100" /></a></p>
<p>Each project has a dashboard. The dashboard is an aggregation of more detailed metrics on a single page. This page gives a pretty good overview of the technical state of a project. When doing project reviews, this page is a good starting point to find items to investigate.</p>
<p>Almost every metric on the dashboard is clickable. When you click on a metric, you get more information about violating classes.</p>
<h2>Configuring Metrics</h2>
<p>Sonar uses <a href="http://findbugs.sourceforge.net/" target="_blank">findbugs</a>, <a href="checkstyle.sourceforge.net/" target="_blank">checkstyle</a> and <a href="pmd.sourceforge.net/" target="_blank">PMD</a> to measure your code for bugs, ugly code and possible violation of code style policies. Sonar comes with a pretty good basic configuration, but the chance is big that you want to fiddle with the settings.</p>
<p>The easiest way is to take a basic configuration and make a copy of it. You can then change the configuration as you like. Note that you have to tell Sonar which projects should use this configuration.</p>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/02/configuration1.png"><img class="alignnone size-full wp-image-1872" title="configuration" src="http://blog.jteam.nl/wp-content/uploads/2010/02/configuration1.png" alt="" width="200" height="100" /></a> <a href="http://blog.jteam.nl/wp-content/uploads/2010/02/project_profiles1.png"><img class="alignnone size-full wp-image-1871" title="project_profiles" src="http://blog.jteam.nl/wp-content/uploads/2010/02/project_profiles1.png" alt="" width="200" height="100" /></a></p>
<p>Note that you must be logged in to be able to change the configuration. By default, there is one user, with username and password “admin”.</p>
<p>Another way to create a configuration is by specifically creating a new one. This is useful if you already have checkstyle, PMD and findbug configurations in your organization. You can then upload these files when creating your new configuration.</p>
<h2>Sonar Database Configuration</h2>
<p>The default configuration works nicely if you have Sonar installed locally and don&#8217;t mind to use the default Derby Database. For larger development environments, however, this default configuration is not enough.</p>
<p>You can configure Sonar to use a database quite easily. The “sonar.properties” file contains the basic Sonar configuration. Configuration examples are available for most databases. All you need to do is uncomment a block of configuration and make sure the URL, username and password are correct.</p>
<p>In maven, you have to configure the same URL’s. Personally, I find that a little awkward, since you need to share database details over multiple applications.</p>
<p>You can configure Sonar in your pom.xml file, which makes the configuration accessible to the projects using that pom. The following example configures a MySQL database.</p>
<pre class="brush: xml;">&lt;project&gt;
  &lt;properties&gt;
    &lt;sonar.jdbc.url&gt;jdbc:mysql://my_sonar_db:3306/sonar?useUnicode=true&amp;amp;characterEncoding=utf8&lt;/sonar.jdbc.url&gt;
    &lt;sonar.jdbc.driver&gt;com.mysql.jdbc.Driver&lt;/sonar.jdbc.driver&gt;
    &lt;sonar.jdbc.username&gt;sonar_user&lt;/sonar.jdbc.username&gt;
    &lt;sonar.jdbc.password&gt;sonar_pass&lt;/sonar.jdbc.password&gt;
    &lt;sonar.host.url&gt;http://my_sonar_url:9000&lt;/sonar.host.url&gt;
  &lt;/properties&gt;
&lt;/project&gt;</pre>
<p>Alternatively, you can pass all these parameters in the maven command line, or configure your maven settings.xml (on your build server, for example) to set these parameters.</p>
<h2>Metrics don’t say it all</h2>
<p>Although I believe that Sonar is a very nice tool to create code quality awareness, metrics don’t say it all. Some quality aspects simply cannot be caught in a metric. Just solving the issues that Sonar arises is not a good way to improve quality. Sonar can show problem area’s. It is up to the development team to find out where these problems come from, and solve them.</p>
<p>No matter how good the metrics are, each and every software project still needs a <a href="http://www.jteam.nl" target="_blank">good process</a>, a <a href="http://www.jteam.nl" target="_blank">good project management</a>, a <a href="http://www.jteam.nl" target="_blank">hands-on architect</a> and a <a href="http://www.jteam.nl" target="_blank">smart development team</a> to become a success.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/02/26/measuring-code-quality-with-sonar/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Wicket root mounts</title>
		<link>http://blog.jteam.nl/2010/02/24/wicket-root-mounts/</link>
		<comments>http://blog.jteam.nl/2010/02/24/wicket-root-mounts/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 21:00:27 +0000</pubDate>
		<dc:creator>Erik van Oosten</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=1650</guid>
		<description><![CDATA[One of the very easy things with Wicket is mounting pages on the first words of a URL; listening to URLs like http://shop.nl/article/4513 is programmed before you can say xiphophorus clemenciae.
One of the very hard things with Wicket is mounting pages where the first words of the URL are a parameter; listening to a URL [...]]]></description>
			<content:encoded><![CDATA[<p>One of the very easy things with Wicket is mounting pages on the first words of a URL; listening to URLs like <code>http://shop.nl/article/4513</code> is programmed before you can say xiphophorus clemenciae.<br />
One of the very hard things with Wicket is mounting pages where the first words of the URL are a parameter; listening to a URL like <a href="http://twitter.com/erik_van_oosten">http://twitter.com/erik_van_oosten</a> is just completely impossible.</p>
<p>Completely impossible? Wicket 1.5 will make this easy but is very instable for now. This article shows you how to mount pages <em>on the root</em> URL with Wicket 1.4. We will need to apply some hacks so hang on!</p>
<p><em>If you are only interested in using the technique you can skip to the last section &#8216;Understanding the demo&#8217;.</em></p>
<p><span id="more-1650"></span></p>
<p>Note: when all URLs in your site start with a predictable and/or common parameter (like the locale in <code>/en/timetable/thisweek</code>) you are better of with URL rewriting (e.g. to <code>/timetable/thisweek?lang=en</code>). This article focuses on URLs that start with a very flexible word (as in <code>http://www.hotel.com/<em>amsterdam</em></code> and <code>http://www.tipspot.com/<em>sarah</em>/agenda</code>).</p>
<h3>Terminology</h3>
<p>Before we dive in the details, we first need to get some terminology straight:</p>
<dl>
<dt>Mount path</dt>
<dd>A URL prefix for which you want to parse the URL in a certain way. For example <code>/article</code> is the mount path for all article pages.</dd>
<dt>URL mounting</dt>
<dd>Shorthand for mounting a URL strategy; e.g. calling <code>WebApplication.mount</code> in your <code>Application.init</code> method. The effect is that URLs with the given mount path are processed by the given target page.</dd>
<dt>Root mount</dt>
<dd>Mounting a URL strategy for some URLs, but <em>without</em> a mount path, and some given target page.</dd>
<dt>URL strategy</dt>
<dd>This term is my abbreviation for Wicket&#8217;s <code>IRequestTargetUrlCodingStrategy</code>; a piece of code that can parse and encode URLs. Url strategies are normally associated with a single <em>mount path</em> and a target page.</dd>
<dt>Root URL strategy</dt>
<dd>My term for a URL strategy that does not need a mount path to parse and encode URLs for some target page.</dd>
</dl>
<h3>Tricking Wicket &#8211; the fake mount path</h3>
<p>By default Wicket uses a mount path to select one of the the mounted URL strategies, effectively selecting a page based on the first words of a URL. This works quite well until you want an empty mount path. So how do we get around this? The trick is to fake it! Just before the URL is decoded (parsed) by Wicket we add a &#8216;fake&#8217; mount path. Similarly just before a Wicket encoded URL is put in a HTML page, we remove the &#8216;fake&#8217; mount path.</p>
<p>The advantage of this approach is that we can reuse lots of Wicket code and not have to write our own URL decoding and encoding. We simply extend the existing implementations of <code>IRequestTargetUrlCodingStrategy</code> (e.g. <code>IndexedParamUrlCodingStrategy</code>, <code>MixedParamUrlCodingStrategy</code>, etc.).</p>
<p>So that&#8217;s the basic idea. We still need to jump through some hoops to make it work.</p>
<h3>Selecting a root URL strategy</h3>
<p>Having a fake mount path does not give you a way to select the desired root mounted URL strategy. The fake mount path is really fake, it is only present <em>after</em> a URL strategy has been selected.</p>
<p>To enable the selection process I introduce a simple interface which our root URL strategies have to implement:</p>
<pre class="brush: java;">
interface RootMountedUrlCodingStrategy {
  boolean accepts(String rawPath);
}
</pre>
<p>The first root URL strategy to return true will be the selected URL strategy.</p>
<p>We can hookup a list of root URL strategies in a custom request cycle processor. Our custom request cycle processor extends <code>UrlCompressingWebRequestProcessor</code> (because it gives nicer URLs for non-mounted pages) and overrides <code>newRequestCodingStrategy</code> to return our custom <code>IRequestCodingStrategy</code> which extends <code>UrlCompressingWebCodingStrategy</code> and overrides <code>IRequestTargetUrlCodingStrategy urlCodingStrategyForPath(String path)</code>. For more details see the code in the demo. One thing you might notice is that the root URL strategies are only consulted when no regular Wicket mount path was detected.</p>
<h3>Adding and removing the fake mount path</h3>
<p>The second hoop is that we can only <em>remove</em> the &#8216;fake path&#8217; in the <code>encode</code> method of <code>IRequestTargetUrlCodingStrategy</code> implementations, <em>adding</em> it in the <code>decode</code> method as well will confuse Wicket too much. To solve this, our custom <code>IRequestCodingStrategy</code> of the previous section also overrides <code>String getRequestPath(Request request)</code>. This is slightly tricky as we do not want to touch URLs for regular mounted paths.</p>
<p>To complete the Wicket trickery, <code>RootMountedUrlCodingStrategy</code> will extend <code>IRequestTargetUrlCodingStrategy</code> (so that it becomes a full URL strategy) and it will be mounted on the fake mount path so that Wicket can find it to encode URLs.</p>
<h3>Implementing <code>RootMountedUrlCodingStrategy</code></h3>
<p>Now we need to implement instances of <code>RootMountedUrlCodingStrategy</code>. In general what you want is behavior similar to one of the URL strategies that extend from <code>BookmarkablePageRequestTargetUrlCodingStrategy</code> (with subclasses like <code>IndexedParamUrlCodingStrategy</code> and <code>MixedParamUrlCodingStrategy</code>). Unfortunately the method we need to override, <code>encode(IRequestTarget)</code>, is final. Our third hoop. Bummer.</p>
<p>When there is a strong need to override a method that Wicket made final (mostly with good reason), I usually just copy the Wicket class to my own sources and make sure it has the same package. Your own classes are sure to be earlier on the classpath and therefore take precedence over the classes from the Wicket jar. An infinitely better way would be to build your own version of Wicket (for example by cloning the repository on github). In the demo I just use the hacky way.</p>
<h3>Understanding the demo</h3>
<p>The demo is a Wicket quickstart. That means that it uses Maven 2. After you unzipped it you can do a <code>mvn jetty:run</code> to start it immediately. See <a href="http://wicket.apache.org/quickstart">the Wicket quickstart page</a> to see how you hook it up in your IDE. Once that is done, just run the <code>Start</code> class to start the application in an embedded Jetty container. Browse to <a href="http://localhost:8080/">http://localhost:8080/</a> to see the root mounts in action.</p>
<p>In the code you&#8217;ll find the following packages:</p>
<dl>
<dt><code>nl.jteam.example</code></dt>
<dd>Contains the example application. For configuration see the class <code>WicketApplication</code>.</dd>
<dt><code>nl.jteam.rootmount</code></dt>
<dd>Contains all the code to make root mounts possible. These can be copied to your project ad verbatim.</dd>
<dt><code>org.apache.wicket.request.target.coding</code></dt>
<dd>Monkey-patch to remove a &#8216;final&#8217; keyword in the Wicket code base (see comment above).</dd>
</dl>
<p>If you open <code>WicketApplication</code> you will notice 2 root mounts and one traditional mount. The first root URL strategy listens for &#8216;cities&#8217; with an optional subject; <code>/amsterdam</code> and <code>/paris/theatre</code> and is associated with <code>CityPage</code>. The second root URL strategy listens for &#8216;members&#8217;; <code>/alice</code> and <code>/bob</code> and is associated with <code>MemberPage</code>. The traditional mount couples mount path <code>tokyo</code> to page <code>TokyoPage</code>. Other code wires up the custom request cycle processor.</p>
<p>As a bonus <code>WicketApplication</code> shows you how to use a &#8216;not found&#8217; page from within Wicket (commented out). Take note however that this removes the fall-back request-handling of the servlet container. See the comments on how to enable it. You have been warned!</p>
<p>To keep things interesting &#8216;paris&#8217; is both the name of a city and that of a member. The city Paris &#8216;wins&#8217; because it is the first root URL strategy (see what happens if you change the order). Furthermore, &#8216;Tokyo&#8217; is a recognized city. URL <code>/tokyo</code> will however not lead to the <code>CityPage</code> as traditional mounts take precedence.</p>
<p>Package <code>nl.jteam.rootmount</code> also contains a couple of base classes that take the angle out of properly implementing <code>RootMountedUrlCodingStrategy</code>. They are: <code>RootMountedBookmarkablePageRequestTargetUrlCodingStrategy</code>, <code>RootMountedIndexedParamUrlCodingStrategy.java</code>, <code>RootMountedMixdedParamUrlCodingStrategy.java</code> and <code>RootMountedQueryStringUrlCodingStrategy.java</code>. They correspond to the normal Wicket equivalents. All you have to do is extend them and implement <code>boolean accepts(String rawPath)</code>. Examples are <code>CityPageUrlCodingStrategy</code> and <code>MemberPageUrlCodingStrategy</code>.</p>
<h3>Using root mounts in your project</h3>
<p>To apply this technique in your own application, copy the package <code>nl.jteam.rootmount</code> to your own project and wire it up similarly as in the demo&#8217;s <code>WicketApplication</code>. In addition you will need to remove a &#8216;final&#8217; keyword from the Wicket class <code>BookmarkablePageRequestTargetUrlCodingStrategy</code>. See section &#8216;Implementing <code>RootMountedUrlCodingStrategy</code>&#8216; above for more information.</p>
<p>If you implement your own root URL strategies, take note that the <code>accept</code> method might be called quite often. It is prudent to make sure this method returns quickly.</p>
<h3>Conclusion</h3>
<p>This article shows that it <em>is</em> possible to have root mounts in Wicket 1.4. The downloadable demo application shows that it is even possible with a simple API. However, the implementation has to jump through some hoops to make this possible, and some of these hoops are not pretty at all.</p>
<h3>Download the demo</h3>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/02/wicket-rootmount-demo.tar.gz"><img class="pinkynail toggle" src="http://blog.jteam.nl/wp-includes/images/crystal/archive.png" alt="" style="vertical-align:middle"> wicket-rootmount-demo.tar.gz</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/02/24/wicket-root-mounts/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Greg Young to attend on DDDnl meetup about CQRS on March 1st.</title>
		<link>http://blog.jteam.nl/2010/02/24/greg-young-to-attend-on-dddnl-meetup-about-cqrs-on-march-1st/</link>
		<comments>http://blog.jteam.nl/2010/02/24/greg-young-to-attend-on-dddnl-meetup-about-cqrs-on-march-1st/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 16:21:43 +0000</pubDate>
		<dc:creator>Allard Buijze</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[User Group]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/2010/02/24/greg-young-to-attend-on-dddnl-meetup-about-cqrs-on-march-1st/</guid>
		<description><![CDATA[On March 1st, Erik Rozendaal will give a presentation about Command Query Responsibility Seggregation (CQRS). Greg Young, one of the masterminds behind CQRS, has confirmed that he will be present during this meetup too. Seems like a good recipe for an interesting evening.
Attendance is free, but registration is required. Read on for details.
 
About the [...]]]></description>
			<content:encoded><![CDATA[<p>On March 1st, Erik Rozendaal will give a presentation about Command Query Responsibility Seggregation (CQRS). Greg Young, one of the masterminds behind CQRS, has confirmed that he will be present during this meetup too. Seems like a good recipe for an interesting evening.</p>
<p>Attendance is free, but registration is required. Read on for details.</p>
<p> <span id="more-1840"></span><br />
<h2>About the meetup</h2>
<p>The Domain Driven Design Netherlands User Group (DDDnl) organizes bi-monthly meetups where software developers, architects, product owners and managers join to discuss DDD related issues. During each meetup, one of our members gives a presentation. The upcoming meetup will cover the concept of CQRS.</p>
<p>Command-Query Responsibility Segregation (CQRS) is a technique developed by Greg Young that combines the Event Sourcing pattern with Domain-Driven Design. This provides various benefits, amongst others: a fully encapsulated domain model without the need for any ORM tools, separate query and reporting database, 100% correct historical information, and easy integration with other systems.</p>
<p>In this presentation we&#8217;ll cover the core concepts of Command-Query Responsibility Segregation, its impact on the application&#8217;s architecture, and the various advantages and disadvantages. Some (Java) code will be shown to highlight how such a system can be implemented.</p>
<h2>Time and location</h2>
<p>The meetup will be held at the JTeam Head Office at Frederiksplein 1, Amsterdam. Check <a href="http://www.jteam.nl/contact">http://www.jteam.nl/contact</a> for directions.</p>
<p>You are welcome from 17:30. We will start with some food, which is expected at 18:00. The presentation starts after dinner.</p>
<h2>Registration</h2>
<p>You can confirm your presence by sending an email to <a href="mailto:info@dddnl.org">info@dddnl.org</a>. Please include your name and a phone number where we can reach you, just in case.</p>
<p>If you want to keep updated about other DDDnl meetings, make sure you register on our website: <a href="http://www.dddnl.org">www.dddnl.org</a> as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/02/24/greg-young-to-attend-on-dddnl-meetup-about-cqrs-on-march-1st/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Axon Framework &#8211; the CQRS framework for Java &#8211; version 0.4 released</title>
		<link>http://blog.jteam.nl/2010/02/21/axon-framework-the-cqrs-framework-for-java-version-0-4-released/</link>
		<comments>http://blog.jteam.nl/2010/02/21/axon-framework-the-cqrs-framework-for-java-version-0-4-released/#comments</comments>
		<pubDate>Sun, 21 Feb 2010 16:04:09 +0000</pubDate>
		<dc:creator>Allard Buijze</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Axon Framework]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[DDD]]></category>
		<category><![CDATA[Domain Driven Design]]></category>
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/2010/02/21/axon-framework-the-cqrs-framework-for-java-version-0-4-released/</guid>
		<description><![CDATA[Last week, I published the 0.4 release of the Axon Framework. Axon helps developers build high performance, scalable and extensible applications using the CQRS pattern. The 0.4 release is a major step towards 1.0, and includes transactional event handling, high-performance caching repositories and easy configuration of event sourcing support. Furthermore, we have also built a [...]]]></description>
			<content:encoded><![CDATA[<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="logo" border="0" alt="logo" align="left" src="http://blog.jteam.nl/wp-content/uploads/2010/02/logo.png" width="100" height="100" />Last week, I published the 0.4 release of the Axon Framework. Axon helps developers build high performance, scalable and extensible applications using the CQRS pattern. The 0.4 release is a major step towards 1.0, and includes transactional event handling, high-performance caching repositories and easy configuration of event sourcing support. Furthermore, we have also built a demo application that uses Flex to get real-time updates pushed from the server.</p>
<p>Read on to find out more.</p>
<p> <span id="more-1799"></span><br />
<h2>About the Axon Framework</h2>
<p><a name="Axon_Framework"></a></p>
<p>Axon Framework helps build scalable, extensible and maintainable applications by supporting developers apply the Command Query Responsibility Segregation (CQRS) architectural pattern. It does so by providing implementations, sometimes complete, sometimes abstract, of the most important building blocks, such as aggregates, repositories and event the bus – the dispatching mechanism for events. Furthermore, Axon provides annotation support, which allows you to build aggregates and event listeners without tying your code to Axon specific logic. This allows you to focus on your business logic, instead of the plumbing, and helps you makes your code easier to test in isolation.</p>
<h2>Features available in 0.4</h2>
<p>We have made quite a few additions and changes since the 0.3 release. Unfortunately, this also means I had to make some minor API changes. There is now a bigger choice of abstract classes for most of the building blocks. This allows you to choose whether you want to use the logic provided by Axon, or prefer to develop more of your own. Whatever your wish is, there should be a class to help you on your way.</p>
<p>The biggest change since 0.3 is the addition of an Asynchronous Event Bus that supports transactional processing of events. Since it is asynchronous, it means that your command processing doesn’t have to wait for events to be processed. However, this Event Buss can also guarantee the order in which events are delivered to the event handlers. You can choose full concurrent processing (without any guarantees about ordering), full sequential processing (FiFo guarantee) or anything in between. You could, for example, guarantee the sequential processing of Events that come from the same aggregate.</p>
<p>The Event Bus also provides transaction support. That means you can tell the event bus to retry an event after a certain amount of time when processing fails, for example due to an error in the underlying mechanism, such as a database. For performance reasons, you can configure the event handler to process multiple events within a single transaction. Database updates are a lot faster if you process several events within a single transaction before committing it. Within your event handler, you can configure transactions. </p>
<p>Besides Domain Events, Axon now also allows you to explicitly define two other types of events: Application Events and System Events. Application Event can notify your event listeners that something interesting happened in your application. System Events are a special type of application events and can be used to indicate that a part of your application has changed state, for example when the database is no longer available. These System Events could provide interesting operational information about your application.</p>
<p>Another major change since 0.3 is the documentation. We have brought the documentation up to par with the code-base. All features are now extensively described in the reference guide. You can download the manual from the Axon Framework website: <a href="http://www.axonframework.org" target="_blank">www.axonframework.org</a>.</p>
<p>Last, but definitely not least, we have created a demo application that you can easily download and deploy to have a look at how you can use events to your advantage. This demo application is built using a Flex Client and an Axon-based server side component. The Flex Client registers itself as an event listener and will automatically process incoming events, at real time! That means that you can have 2 windows open, change something in one window, and see the change come in immediately on the other window, too. Check our <a href="http://code.google.com/p/axonframework/wiki/SampleInstallation" target="_blank">Sample Installation</a> page for more information.</p>
<h2>What to expect in upcoming releases</h2>
<p>The major components of the CQRS pattern are already available in the 0.4 release of Axon Framework. However, there is still a number of features we want to include in the 1.0 release. Although one of the advantages of CQRS is that it makes an application scalable and extensible, the 1.0 release of Axon Framework focuses on what happens inside a single JVM. Streaming events between JVM’s is not made impossible though, the Spring Integration connectors can be used to publish events to JMS, MQ, mail, HTTP and any other protocol supported by Spring Integration.</p>
<p>Some features to expect before the 1.0 release are rolling snapshots. When aggregates live for a long time, the number of events to read in each time the aggregate is loaded could easily run in the thousands. Reading in a thousand events takes a long time. Instead of reading in a thousand events, you can summarize all these events into a single snapshot event. Axon Framework will provide the plumbing necessary for you to build snapshot events.</p>
<p>Another feature that we’ll be spending some attention on is failure recovery. Unfortunately, applications sometimes behave unexpectedly and sometimes stop entirely. The reason of a crash won’t be the Axon Framework itself, of course. But since we have a reliable source of events in the events store, we can use this to recover from failure. Axon Framework will provide some building blocks that allow you to republish events to event handlers that did not get the chance to process them. This same mechanism will allow you to restore your application state from backups.</p>
<p>The last feature currently on the roadmap is JMX support. Since Axon Framework deals with the dispatching and invocation of event handlers, it has interesting information about an application’s performance and technical state. We are planning to expose this information using JMX MBeans.</p>
<p>If you have any other ideas, you can submit a feature request on <a href="http://www.axonframework.org/issues" target="_blank">www.axonframework.org/issues</a>. </p>
<h2>Getting started with Axon</h2>
<p>If you&#8217;re eager to get started using Axon Framework for your own application, check out the <a href="http://www.axonframework.org" target="_blank">Axon Framework website</a>. There, you can download the binaries, sources documentation and a sample application. If you use Maven, the reference manual will explain how you can configure the dependencies on the Axon binaries.</p>
<p>If the information on the website is not enough to get you started, don’t hesitate to send me a message or post a comment at the bottom of this blog entry.</p>
<h2>A special thanks to…</h2>
<p>Before I wrap up, I would like to thank Jettro Coenradie for his help on the sample project and the reference documentation. I think the sample turned out into a pretty cool demo environment for some of the advantages that Axon can provide.</p>
<p>Also many thanks to <a href="http://www.jteam.nl" target="_blank">JTeam</a> for the time they allowed me to spend on the project. Without it, I am sure I couldn’t have delivered this release. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/02/21/axon-framework-the-cqrs-framework-for-java-version-0-4-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free Java hosting with the Google App Engine</title>
		<link>http://blog.jteam.nl/2010/02/04/free-java-hosting-with-the-google-app-engine/</link>
		<comments>http://blog.jteam.nl/2010/02/04/free-java-hosting-with-the-google-app-engine/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 14:31:41 +0000</pubDate>
		<dc:creator>Tom van Zummeren</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Spring Framework]]></category>
		<category><![CDATA[Support]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=1664</guid>
		<description><![CDATA[Lately I have been looking into and playing around with the Google App Engine. In this post I want to give a little introduction to the Google App Engine, why it can be interesting and how to work with it.

Introduction
First I want to describe what the Google App Engine is in a few sentences. But [...]]]></description>
			<content:encoded><![CDATA[<p>Lately I have been looking into and playing around with the <a href="http://code.google.com/appengine">Google App Engine</a>. In this post I want to give a little introduction to the Google App Engine, why it can be interesting and how to work with it.<br />
<span id="more-1664"></span></p>
<h2>Introduction</h2>
<p>First I want to describe what the Google App Engine is in a few sentences. But nobody does a better job at explaining than Wikipedia so I&#8217;ll just give you a quote instead <img src='http://blog.jteam.nl/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<blockquote><p>
Google App Engine is a platform for developing and hosting web applications in Google-managed data centers. It was first released as a beta version in April 2008.<br />
Google App Engine is cloud computing technology. It virtualizes applications across multiple servers and data centers.[1] Other cloud-based platforms include offerings such as Amazon Web Services and Microsoft&#8217;s Azure Services Platform.<br />
Google App Engine is free up to a certain level of used resources. Fees are charged for additional storage, bandwidth, or CPU cycles required by the application.
</p></blockquote>
<p>Source: <a href="http://en.wikipedia.org/wiki/Google_App_Engine">http://en.wikipedia.org/wiki/Google_App_Engine</a></p>
<p>To sum this quote up in a few words: Google App Engine is free hosting for Java! For so long technologies like <a href="http://www.php.net">PHP</a> have been very cheap (if not free) to host. To host a Java web application on the other hand, you always have to pay good money for it. Probably the biggest reason is that for PHP, it&#8217;s easy to have many websites on one server since those websites are just a bunch of standalone scripts. A Java website on the other hand, is an entire application, so the best way to host this is to get a dedicated server with an application server installed. Dedicating an entire server to host your website usually isn&#8217;t as cheap as hosting a PHP website.</p>
<h2>Why use the Google App Engine?</h2>
<p>Next to the fact that Google App Engine is free to use, what else is interesting about it, you ask? Well, let me tell you! Actually, Google App Engine offers you a lot of features which can help your application in different ways. Below are a few examples of features I find the most helpful.</p>
<h3>The dashboard</h3>
<p>The first thing you will see when you start using the Google App Engine is the Dashboard. The dashboard has both an online version and a local development version.</p>
<p>The online version of the dashboard allows you to see all sorts of information about your deployed application. You can for example see application logging (filtered by INFO, WARN, etcetera), but also configured cron jobs, the content of your data store and quota details.</p>
<p>The local development dashboard is kind of a stripped down version of the online one. It helps you control your locally running instance of the application. Using the dashboard you can for example simulate incoming emails, simulate incoming XMPP messages and view running cron jobs.</p>
<h3>Image service</h3>
<p>Google offers you a service to easily manipulate images. The most common image operations are supported, like: resizing, cropping, flipping, enhancing colors and contrast.</p>
<h3>Data store</h3>
<p>Using Google&#8217;s JPA or JDO implementation you can access the datastore. You can also use an SQL-like query language to access the store directly.</p>
<h3>Cron jobs / task queues</h3>
<p>Instead of using a framework like <a href="http://www.quartz-scheduler.org/">Quartz</a> to schedule jobs, Google App Engine takes care of executing jobs for you. You simply enter a cron-like expression and a URL to call and your job is configured.</p>
<p>You also have a task queue at your disposal. Your application code can add tasks to a task queue which will be executed later in the future, asynchronously. An example use case is that you don&#8217;t want clients to wait for an email to be sent before he sees the next page. Instead you can put the email task on the task queue and the email will be sent asynchronously.</p>
<h3>Security using Google accounts</h3>
<p>Why use a security framework like <a href="http://static.springsource.org/spring-security/site/index.html">Spring Security</a> when Google lets you use their own authentication system? When you configure your application to use Google authentication, only people with a Google account are able to login to the application. You can also configure one or more accounts to be the administrator. Administrators could have access to certain parts of the application other users can&#8217;t access.</p>
<h3>Service for receiving email</h3>
<p>Google offers a service that allows your application to receive emails! When an email comes in, a URL is called with the email in the POST body. The body of the request is just the plain mime message text as it was received.</p>
<h2>Applications on the Google App Engine</h2>
<p>To run your own application on the Google App Engine, it has to follow some guidelines in order to properly function. When I was building a sample application, I sometimes found myself writing workarounds to work with for example the JPA and mailing facilities of the Google App Engine. For the record, I was trying to use the Spring framework with JPA for persistence and Spring MVC for the frontend. I want to share the challenges I faced and how I handled them to get things working. </p>
<p>Sometimes I had to write custom classes to get things working, I combined all those classes in a tiny open source project called app-engine-workarounds. The project can be found at <a href="http://code.google.com/p/app-engine-workarounds/">http://code.google.com/p/app-engine-workarounds/</a>. Below I will sometimes refer to classes in this project.</p>
<h3>Spring and the Java Mail Sender</h3>
<p>When you&#8217;re using Spring and want to send an email from within your application, you will use the <a href="http://static.springsource.org/spring/docs/3.0.0.RELEASE/api/org/springframework/mail/javamail/JavaMailSenderImpl.html">JavaMailSenderImpl</a> which is packaged with Spring. But when running an application the Google App Engine, you can&#8217;t use this class out-of-the-box. The reason is that Google has its own email implementation and does not use SMTP servers for instance. This is why you have to interact differently with the javax.mail.* framework. Luckily you can easily extend the JavaMailSenderImpl to make adjustments. The <a href="http://code.google.com/p/app-engine-workarounds/">app-engine-workarounds</a>s library actually contains an adjusted JavaMailSender which is called the GaeJavaMailSender. This class is a drop-in replacement for the original JavaMailSenderImpl.</p>
<h3>Handling file uploads in Spring MVC</h3>
<p>Handling file uploads in Spring MVC requires an implementation of the <a href="http://static.springsource.org/spring/docs/3.0.0.RELEASE/api/org/springframework/web/multipart/MultipartResolver.html">MultipartResolver</a>. The only implementation available in Spring MVC 3.0 is the <a href="http://static.springsource.org/spring/docs/3.0.0.RELEASE/api/org/springframework/web/multipart/commons/CommonsMultipartResolver.html">CommonsMultipartResolver</a> which uses <a href="http://commons.apache.org/fileupload/">commons-fileupload</a> to do its job. Unfortunately the way Spring uses commons-fileupload, is not supported by the Google App Engine because it uses the file system, which Google App Engine does not provide. To make this work, you will have to utilize the <a href="http://commons.apache.org/fileupload/streaming.html">streaming API</a> part of commons-fileupload framework, which does not need the filesystem. I created my own custom implementation of the MultipartResolver that actually uses this streaming API of commons-fileupload. I put this implementation in the <a href="http://code.google.com/p/app-engine-workarounds/">app-engine-workarounds</a> library too.</p>
<h3>Spring and JPA with transactions</h3>
<p>You can use JPA with Spring almost like you&#8217;re used to, except that the EntityManager factory bean is configured differently. In the section &#8220;Other workarounds&#8221; on <a href="http://code.google.com/p/app-engine-workarounds/">http://code.google.com/p/app-engine-workarounds/</a> I put a description of how to configure JPA in Spring for the Google App Engine.</p>
<p>Using JPA with the Google App Engine has its limitations. I only tried the JPA implementation and I soon found out that a lot of JPA features are not (yet) supported. Most of these features are related to relationships between entities. I used a relatively simply data model and already encountered the following issues:</p>
<ul>
<li>Multiple ManyToOne relations to the same entity is not supported</li>
<li>OneToMany relation can only be used with entities that use the GAE &#8220;Key&#8221; class as the unique identifier</li>
<li>Can&#8217;t operate on multiple entities within the same transaction</li>
<li>In a query, you can&#8217;t use &#8220;OR&#8221; filtering referring to two different properties of an entity</li>
</ul>
<h3>Parsing inbound emails</h3>
<p>Google App Engine offers the very useful feature of receiving emails in your application. This way users can just send an email to some address and your application processes it. When an email is received Google App Engine does a post on an URL in your application you configured. The HTTP body of the POST request contains the exact mime message as it was received by Google. To parse this mime message you can use the <a href="http://java.sun.com/products/javamail/javadocs/javax/mail/internet/MimeMessage.html">MimeMessage</a> class provided by the JDK. </p>
<p>Unfortunately this class is not easy to use and sometimes not that straightforward at all. Usually all you want is to extract the sender, subject, body (html or plain text version) and attachments from the mime message. I created a few classes that help you to easily parse that information from a mime message received by your application. And guess what? I put these classes in the <a href="http://code.google.com/p/app-engine-workarounds/">app-engine-workarounds</a> project too! Example of how to parse an incoming email message using this class:</p>
<pre class="brush: java;">
Session session = Session.getDefaultInstance(new Properties(), null);
MimeMessage mimeMessage = new MimeMessage(session, request.getInputStream());
EmailMessage email = new EmailMessage(mimeMessage);

// Now you can use the EmailMessage instance to easily extract information
String subject = email.getSubject();
String plainTextBody = email.getPlainTextBody();
String htmlBody = email.getHtmlBody();
Address fromAddress = email.getFromAddress();
List&lt;Attachment&gt; attachments = email.getAttachments();
// ... etcetera
</pre>
<h3>Cronjob to keep your application &#8220;hot&#8221;</h3>
<p>When you deploy your application it doesn&#8217;t always keep running. After like 5 minutes of inactivity, the application shuts down. Now when a user tries to access a URL, the application starts up again. So the first user that tries to open a page after a period of inactivity has to wait 30 seconds before he gets a response. Google does this to save CPU power of the servers in their &#8220;cloud&#8221;. </p>
<p>Especially during development, this is very annoying because it slows you down trying to test your application. What you can do is configure a cronjob with the expression &#8220;every 1 minutes&#8221; which calls the URL &#8220;/ping&#8221; (for example). When this is in place, your application always stays &#8220;hot&#8221;. In other words, it never shuts down and will always quickly respond to requests. I&#8217;m not sure if this violates any usage policy of Google, but I&#8217;m sure it&#8217;s not that bad when you only use this during development, when it&#8217;s the most annoying.</p>
<h3>Google services as Spring beans</h3>
<p>Google exposes a few services for you to use, but you can only get a reference to them using a static factory method. In a Spring application this is not a nice thing to do, especially because this is hard to unit test. Instead, you can configure Google services as Spring beans like this:</p>
<pre class="brush: xml;">
&lt;bean class=&quot;com.google.appengine.api.images.ImagesServiceFactory&quot;
      factory-method=&quot;getImagesService&quot;/&gt;
&lt;bean class=&quot;com.google.appengine.api.users.UserServiceFactory&quot;
      factory-method=&quot;getUserService&quot;/&gt;
...
</pre>
<p>Then you can wire one into the class that needs that service and you&#8217;re done!</p>
<h3>Time zones</h3>
<p>When you use JPA, any date field you&#8217;re trying to persist will get saved using the &#8220;GMT&#8221; timezone. So whenever you want to display dates you have to keep in mind to apply your own timezone to them. When you for example use the <fmt:formatDate/> tag which comes with <a href="http://java.sun.com/products/jsp/jstl/">JSTL</a>, you can configure the time zone in your web.xml like this:</p>
<pre class="brush: xml;">
    &lt;context-param&gt;
        &lt;param-name&gt;javax.servlet.jsp.jstl.fmt.timeZone&lt;/param-name&gt;
        &lt;param-value&gt;GMT+1:00&lt;/param-value&gt;
    &lt;/context-param&gt;
</pre>
<h2>Conclusion</h2>
<p>On one hand Google App Engine provides a rich set of helpful features and services to help you build better applications. On the other hand you do need to compromise by working around certain issues because the Google App Engine doesn&#8217;t entirely behave as a regular application server. Also the JPA implementation in Google App Engine is very limited. But, with the workarounds in place (which I described above) you should be able to get rid of most of the frustrations you will encounter. This way you can start developing your own application like you&#8217;re used to, with the tools you&#8217;re used to but now using all the cool features the app engine offers!</p>
<p>Unfortunately, some frameworks won&#8217;t work at all on the Google App Engine, not even with a workaround. To quickly find out whether a certain framework will work on the app engine, take a look at this page <a href="http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine">http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine</a>. As long as you&#8217;re not using any frameworks on the &#8220;black list&#8221; you will be fine ^^</p>
<p>If anyone else has workarounds or other helpful classes for the Google App Engine, let me know by posting a comment below. I will include them to this blog post and/or to the <a href="http://code.google.com/p/app-engine-workarounds/">app-engine-workarounds</a> project.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/02/04/free-java-hosting-with-the-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>All good things come to an end&#8230;</title>
		<link>http://blog.jteam.nl/2010/01/27/all-good-things-come-to-an-end/</link>
		<comments>http://blog.jteam.nl/2010/01/27/all-good-things-come-to-an-end/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 14:37:27 +0000</pubDate>
		<dc:creator>Leonard Wolters</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Office]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=1725</guid>
		<description><![CDATA[JTeam, Leonard, director, leaving, goodbye, farewell]]></description>
			<content:encoded><![CDATA[<p>Yes it is true. After almost 6 years I&#8217;ve decided to leave JTeam.</p>
<p><img src="http://blog.jteam.nl/wp-content/uploads/2010/01/Mail-Attachment.jpeg" alt="GoodbyeParty" /></p>
<p><span id="more-1725"></span><br />
Why am I leaving JTeam you might wonder? Well to be honest JTeam deserves a new leader.</p>
<p>I&#8217;ve successfully brought JTeam to where it is standing right now; a well respected company full of ambitious &amp; talented employees and satisfied clients. We continuously enjoy what we&#8217;re doing and like to share it with the world, especially with you. But each company grows, and along the way I&#8217;ve noticed that JTeam is about to enter a new phase.</p>
<p>A phase of professional growth, both organic and aggressive, a phase of expansion and of more exciting (inter)national challenges is beginning.</p>
<p>A new phase sometimes requires a new leader, and in this case, I feel it does. JTeam deserves someone who is capable of getting the maximum out of it.  Someone that has proven experience in pushing a company to the next level. And we found him.</p>
<p>I fully enjoyed my years in the role of Managing Director of JTeam. I&#8217;ve learned quite a lot, met a large number of awefully interesting people, succeeded in delivering some really cool projects-  but most of all, really enjoyed working with passionate people. People that always want to learn, get the most out of what they&#8217;re doing and even more important, do it with a smile and in a well respected way.</p>
<p>This also holds for all our clients. Along the years I&#8217;ve met many entrepreneurs and business owners all of whom had wonderful dreams, compelling ideas and exciting projects.</p>
<p>But the thing I like the most is meeting the people behind these ideas, dreams &amp; projects. I sincerely hope that we helped you achieving your goal and guided you well on your never ending journey.</p>
<p>Some people ask me “what&#8217;s next?” and luckily I can quickly answer this question.</p>
<p>I simply do not know what&#8217;s next, except enjoying a well deserved holiday of &#8211; let&#8217;s say &#8211; a couple of months. I will take my time to enjoy my personal life, get some rest, read all the books I got recommended and bought and -hopefully-  will soon be conquering the skies in a helicopter!</p>
<p>One thing is for sure: once I&#8217;m ready, you&#8217;ll hear from me. That might take a couple of weeks, months or years. Or maybe it’ll be a matter of days. Stay tuned!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/01/27/all-good-things-come-to-an-end/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>CQRS &#8211; Designing domain events</title>
		<link>http://blog.jteam.nl/2010/01/27/cqrs-designing-domain-events/</link>
		<comments>http://blog.jteam.nl/2010/01/27/cqrs-designing-domain-events/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 11:27:50 +0000</pubDate>
		<dc:creator>Allard Buijze</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Axon Framework]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[DDD]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/2010/01/27/cqrs-designing-domain-events/</guid>
		<description><![CDATA[ Command-Query Responsibility Segregation (CQRS) is slowly but steadily gaining ground as an architecture that helps developers to develop scalable, extensible and maintainable applications. Events play a major role in this architecture, and the way you design these events greatly influence the extensibility of your application.
In this post, I describe some CQRS event basics and [...]]]></description>
			<content:encoded><![CDATA[<p><a title="AxonFramework logo" href="http://www.axonframework.org" target="_blank"><img style="border-bottom: 0px; border-left: 0px; margin: 5px 10px 10px 0px; display: inline; border-top: 0px; border-right: 0px" title="logo" border="0" alt="logo" align="left" src="http://blog.jteam.nl/wp-content/uploads/2010/01/logo.png" width="100" height="100" /></a> Command-Query Responsibility Segregation (CQRS) is slowly but steadily gaining ground as an architecture that helps developers to develop scalable, extensible and maintainable applications. Events play a major role in this architecture, and the way you design these events greatly influence the extensibility of your application.</p>
<p>In this post, I describe some CQRS event basics and design considerations that help keep your application extensible.</p>
<p> <span id="more-1724"></span><br />
<h2>The role of the domain event</h2>
<p>In CQRS, domain events are the source of all application state changes. The diagram below shows a high-level overview of a CQRS architecture. The separation of the components that deal with commands and those that deal with queries is clearly visible.</p>
<p><img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="cqrs_architecture-highlevel" border="0" alt="cqrs_architecture-highlevel" src="http://blog.jteam.nl/wp-content/uploads/2010/01/cqrs_architecturehighlevel.png" width="420" height="327" /></p>
<p>When a command is executed, it will (most likely) change state of one or more aggregates (see DDD definition of aggregate <a href="http://domaindrivendesign.org/node/88" target="_blank">here</a>). As a result of these state changes, one or more events are dispatched.</p>
<p>These events are picked up by Event Handling Components that do whatever they were built to do. Common Event Handling components are those that update database tables in the query database, or those that send an email notification to a user. You can also use Event Handlers to execute commands on related aggregates.</p>
<p>The command handling component is not aware of the listeners that will act on the generated events. This is an important feature to make an application extensible. The downside is that you cannot foresee how events will be used and what information these event handlers will need.</p>
<h2>Information contained in an event</h2>
<p>Since events are broadcasted throughout the entire application, events should contain the information needed by the variety of possible event listeners that exist or might exist in the future. It is impossible to exactly predict what information is needed by event handling components. However, there are a few guidelines that will cover most of the cases.</p>
<p>Recently, someone asked me for advice on event design. He asked me if it was a good idea to use an “CustomerDetailsModifiedEvent”, which would contain the full customer details of the customer, after the change was applied. Although this sounds safe to do, it will get you in serious trouble at a later stage. I’ll go into that a little later.</p>
<p>Domain events should be as specific as possible. If only the address changed on a Customer, consider using an AddressChangedEvent. That event would then contain the new address. This allows components acting on these events to listen to more specific types of events. If you want to send a (paper) letter to someone if his address changed, the “CustomerDetailsModifiedEvent” won’t get you very far, as you don’t have a way to find out what exactly changed.</p>
<p>In some cases, it might be important to know the state as it was before the command was executed. For example, if it is vital for your application to know whether the person moved to another country (because the letter template is different in these cases, for example), then you should also provide the old address in the event. Since the event is generated by the component that also makes the actual change, this shouldn’t be too hard to implement.</p>
<pre>
<pre class="brush: java;">
public class AddressChangedEvent extends DomainEvent {

    private final Address newAddress;
    private final Address oldAddress;

    public AddressChangedEvent(Address oldAddress, Address newAddress) {
        this.oldAddress = oldAddress;
        this.newAddress = newAddress;
    }

    public Address getNewAddress() {
        return newAddress;
    }

    public Address getOldAddress() {
        return oldAddress;
    }
}
</pre>
</pre>
<p>The code sample above shows the basic information contained in an AddressChangedEvent in case it is important to know the address of a customer before and after the modification. In this sample, the DomainEvent will contain information about the customer on which the address change was applied. Typically, this information is limited to the unique identifier of the aggregate.</p>
<h2>Include the intent of the change</h2>
<p>Let’s assume that our business case requires us to send a letter to each customer that changes address. This letter serves as some sort of validation that the address exists and gives the customer feedback that the address change was successfully handled.</p>
<p>In CQRS, we would just create a Event Handling Component that listens to events of type AddressChangedEvent and automatically send a letter to this customer. The information needed for the letter, such as customer name and gender are queried in the query database, since they are not contained in the event itself.</p>
<p>Consider an event with the following information:<br />
  <br />AddressChangedEvent {</p>
<p>- aggregateId 123</p>
<p>- newAddress (“someStreat 2”, &quot;13432”, “SomeCIty”) &lt;- notice the typo in the street name</p>
<p>- oldAdress (…)</p>
<p>As a result of this event, a letter is sent. It is very unlikely that the typo in the street name will cause the letter not to arrive at the destination.</p>
<p>A little later, a sales representative notices the typo in the street name and want to change the address. This change will cause another letter to be sent, most likely to the same address. That’s not really the signal the business likes to send out.</p>
<p>In this scenario, we have captured two different intents of address changes: one is to report that a customer moved to another address, the other is to make a correction in an existing address. The way we deal with these different scenario’s is different.</p>
<p>Some components, like a database updaters, typically don’t care about intent. They will change the address to the new one, regardless of the reason. Furthermore, the information needed by listeners in both scenario’s is identical.</p>
<p>When designing events, consider making an abstract event type that defines “what” has changed. For example, an abstract AddressChangedEvent. We make it abstract, because we never want an instance of this type. This abstract then has a subclass for each intent of the change, representing the “why” of the state change. For example, AddressCorrectionEvent and CustomerMovedEvent. Since they both extend the abstract AddressChangedEvent, the both contain information about the old and new address.</p>
<p>Our event handling components now have a choice. If they don’t care about intent, such as the database updater, they will handle the abstract AddressChangedEvent. If they do, like our letter sender, they can listen to intent specific subclasses. In this case, the letter sender would only act on events of type CustomerMovedEvent.</p>
<h2>Event immutability</h2>
<p>Domain events represent a notification of a state change of an aggregate. It is a representation of something that happened. Whatever you do, what happened has happened. That said, it doesn’t make much sense to change any information in the event while it is being processed.</p>
<p>In CQRS, events are ubiquitous. This means that any component anywhere in the application could listen to any event. Once properties on these events start to change, it is very hard (if not impossible) to predict which component saw which information on the event.</p>
<p>Therefore, make sure all information contained in the event is immutable. At least from the time the event is dispatched. In java, and likely also in other programming languages, making fields immutable provide valuable multi-threading guarantees.</p>
<h2>Event design in the Axon Framework</h2>
<p>Recently, we released version 0.3 of the Axon Framework, an open source framework that helps you with the implementation of applications with a CQRS architecture. Axon Framework provides base implementations for most of the components that make up a CQRS architecture, such as some base classes for events.</p>
<p>All domain events should extend the abstract DomainEvent class. Axon will then ensure that the correct aggregate identifier is registered on the event and will also set a sequence number on the event that allows you to see in which order events were generated for an aggregate. However, the rules and guidelines mentioned above still apply to all domain events.</p>
<p>Starting at version 0.4 (planned for release mid February 2010), Axon Framework also provides support for Application Events and System Events. The former are events that do not represent a state change in an aggregate, but might be of importance to event handling components. The latter provide information about state changes of application components. They could, for example, report that a database is down or a mail server cannot be reached.</p>
<p>For more information about the Axon Framework, visit the project website: <a href="http://www.axonframework.org" target="_blank">www.axonframework.org</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/01/27/cqrs-designing-domain-events/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>First Dutch Lucene User Group Meetup</title>
		<link>http://blog.jteam.nl/2010/01/20/first-dutch-lucene-user-group-meetup/</link>
		<comments>http://blog.jteam.nl/2010/01/20/first-dutch-lucene-user-group-meetup/#comments</comments>
		<pubDate>Wed, 20 Jan 2010 10:50:09 +0000</pubDate>
		<dc:creator>Uri Boness</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Enterprise Search]]></category>
		<category><![CDATA[Lucene]]></category>
		<category><![CDATA[Search]]></category>
		<category><![CDATA[Solr]]></category>
		<category><![CDATA[User Group]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=1654</guid>
		<description><![CDATA[August last year, we announced the new Dutch Lucene User Group with the intention to provide a platform for knowledge sharing and discussions for the Lucene community in The Netherlands. Obviously, beyond setting up a dedicated website for that, the main activity of this usergroup should be in the form of periodic meetups. Unfortunately it [...]]]></description>
			<content:encoded><![CDATA[<p>August last year, we <a href="http://blog.jteam.nl/2009/08/26/announcing_lucene_user_group/" target="_blank">announced</a> the new <a href="http://www.lucene-nl.org/" target="_blank">Dutch Lucene User Group</a> with the intention to provide a platform for knowledge sharing and discussions for the Lucene community in The Netherlands. Obviously, beyond setting up a dedicated website for that, the main activity of this usergroup should be in the form of periodic meetups. Unfortunately it didn&#8217;t work out to execute it last year, but this year we would really like to get it going and put more efforts in it, and first step I guess is setting up a first meetup.</p>
<p>So I&#8217;m pleased to announce the first Dutch Lucene User Group Meetup. It will take place on 17th February (Wednesday) at the JTeam headquarters office. This first meetup will be split into two parts:</p>
<ul>
<li>Introduction to the user group and the members. We&#8217;ll have a discussion about what we would all like to see coming out of this user group and what activities we would like to have.</li>
<li>The next part will be more technical. <a href="http://www.beyondtrees.com/" target="_blank">Anne Veling</a> will share with us some of his experience of large scale Solr deployment that he&#8217;s working on.</li>
</ul>
<p>If you wish to attend, please send us an email to: events@lucene-nl.org</p>
<p><strong>Date:</strong> 17th February 2010</p>
<address><span style="font-style: normal;"><strong>Time:</strong> 17:00<br />
<strong>Location: </strong></span></address>
<address>Frederiksplein 1</address>
<address>1017XK Amsterdam</address>
<address>The Netherlands</address>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/01/20/first-dutch-lucene-user-group-meetup/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Logging to the syslog from a java application</title>
		<link>http://blog.jteam.nl/2010/01/14/logging-to-the-syslog-from-a-java-application/</link>
		<comments>http://blog.jteam.nl/2010/01/14/logging-to-the-syslog-from-a-java-application/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 16:16:42 +0000</pubDate>
		<dc:creator>Jettro Coenradie</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Log4J]]></category>
		<category><![CDATA[Logging]]></category>
		<category><![CDATA[Syslog]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=1648</guid>
		<description><![CDATA[ Every application needs logging, it can help you during development and when debugging those annoying things that do not work in production. One question is where to put the logging events. All linux servers use a system log to log events that take place on the operating system level. You can find logs for the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/01/log4j_logo.jpg"><img class="alignnone size-full wp-image-1659" title="logo log4j" src="http://blog.jteam.nl/wp-content/uploads/2010/01/log4j_logo.jpg" alt="" width="178" height="134" align="left" /></a> Every application needs logging, it can help you during development and when debugging those annoying things that do not work in production. One question is where to put the logging events. All linux servers use a system log to log events that take place on the operating system level. You can find logs for the kernel, deamons, user actions and a lot of other items. The nice part about system logging is that maintenance people will always know where to look and that it is possible to use one server for logging.</p>
<p>At the moment I am on a project that uses a fair amount of servers. We have more than 20 servers for the different environments and a lot of components to investigate when trying to find problems. Think about squid logs, apache httpd logs, tomcat logs and more. To make this doable, we have a syslog server.</p>
<p>An application running in Tomcat does not log to the system log by default. In our situation, we want our components to log to different files. Syslog has a special facility that makes it easy to do just that.</p>
<p>This blog post discusses the different parts of configuring system logging from a java application using the well known log4j.</p>
<p><span id="more-1648"></span></p>
<h2>syslog-ng introduction</h2>
<p>This very short introduction is based on <a href="http://sial.org/howto/logging/syslog-ng/">this article</a>.</p>
<p>With syslog you can log to the local server but also to a remote server. It is also possible to do them both using a little bit of configuration. The following image gives an idea about how a logging environment can be used. (took it from the mentioned article)</p>
<div style="text-align: center;"><img src="http://blog.jteam.nl/wp-content/uploads/2010/01/network-overview.png" border="0" alt="network-overview.png" width="482" height="224" /></div>
<p>Syslog consists of a few elements.</p>
<ul>
<li>Sources &#8211; Where can logs come from, the facilities.</li>
<li>Filters &#8211; Used to for instance log events based on their severity. I used this to filter on Facility</li>
<li>Destinations &#8211; Where to actually send the logs to, a file a remote host.</li>
<li>Logs &#8211; Combine the sources, filters and destinations</li>
</ul>
<p>Before we can talk about the configuration I need to tell you something about Facilities. A facility defines the source of the log. You can think about kernel messages, user-level messages, mail system and many more. The <a href="http://www.jajakarta.org/log4j/jakarta-log4j-1.1.3/docs/api/org/apache/log4j/net/SyslogAppender.html">javadoc of the appender</a> shows the possible values for these Facilities. There are also a few special facilities, these are defined as local0, local1, etc. These are the ones you can use for your own application. We use one of these for every different logfile we want.</p>
<h2>Configure syslog-ng</h2>
<p>The mentioned components are easily identified in the configuration of the syslog. The first thing to configure is udp access to the syslog. To enable udp logging, open the file &#8220;/etc/syslog-ng/syslog-ng.conf&#8221; and make sure to configure the sources part like the following block:</p>
<pre class="brush: plain;">
######
# sources

# all known message sources
source s_all {
# message generated by Syslog-NG
internal();
# standard Linux log source (this is the default place for the syslog()
# function to send logs to)
unix-stream(&quot;/dev/log&quot;);
# messages from the kernel
file(&quot;/proc/kmsg&quot; log_prefix(&quot;kernel: &quot;));
# use the following line if you want to receive remote UDP logging messages
# (this is equivalent to the &quot;-r&quot; syslogd flag)
udp();
};
</pre>
<p>Next up is configure the log files to which the syslog events will be send. First we configure the destination:</p>
<pre class="brush: plain;">
# destinations
destination df_local0 { file (&quot;/var/log/cms.log&quot;); };
destination df_local1 { file (&quot;/var/log/site.log&quot;); };
destination df_local2 { file (&quot;/var/log/importer.log&quot;); };
</pre>
<p>This code block configures three destinations with the names df_local0/1/2 and points them to the mentioned log files. Now we have to filter the incoming log events. We use the facilities that we discussed to filter the incoming events. There are lots of other options, but this is very easy to use. The following lines show the configuration of the filters. </p>
<pre class="brush: plain;">
# filters
filter f_local0 { facility(local0); };
filter f_local1 { facility(local1); };
filter f_local2 { facility(local2); };
</pre>
<p>Finally we configure the logs, these are combinations of a source, a destination and a filter. </p>
<pre class="brush: plain;">
log {
source(s_all);
filter(f_local0);
destination(df_local0);
};
log {
source(s_all);
filter(f_local1);
destination(df_local1);
};
log {
source(s_all);
filter(f_local2);
destination(df_local2);
};
</pre>
<p>Do not forget to restart the syslog service after configuration changes</p>
<h2>Testing to see that it works</h2>
<p>Before you start messing around with log4j, you can use a few tools to send log events to the syslog server. There are command line utilities available on all linux systems. Check <a href="http://linux.byexamples.com/archives/412/syslog-sending-log-from-remote-servers-to-syslog-daemon/" target="_blank">this post</a> for more information. The following command sends a message:</p>
<pre><code>nc 192.168.1.1 514 <<< "<14>User Info msg from remote through TCP."</code></pre>
<p>Be sure to check the port of the server (514 is the default).</p>
<h2>Configure log4j</h2>
<p>The final step is to send syslog events from your java application. Log4j comes out of the box with a SyslogAppender. There is one requirement to be able to use log4j with sys logging. You need to have udp enabled like we discussed in the configuration section. Most of this comes from the mentioned blog post.</p>
<p>An example of log configuration for log4j :</p>
<pre class="brush: plain;">
log4j.rootLogger=INFO, SYSLOG

log4j.appender.SYSLOG=org.apache.log4j.net.SyslogAppender
log4j.appender.SYSLOG.syslogHost=127.0.0.1
log4j.appender.SYSLOG.layout=org.apache.log4j.PatternLayout
log4j.appender.SYSLOG.layout.conversionPattern=%d{ISO8601} %-5p [%t] %c{2} %x - %m%n
log4j.appender.SYSLOG.Facility=LOCAL1
</pre>
<p>That is it, now you have a java application logging to the syslog. Feedback about improvements is welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/01/14/logging-to-the-syslog-from-a-java-application/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Migrating content with Spring Integration &#8211; A real life example</title>
		<link>http://blog.jteam.nl/2010/01/13/migrating-content-with-spring-integration-a-real-life-example/</link>
		<comments>http://blog.jteam.nl/2010/01/13/migrating-content-with-spring-integration-a-real-life-example/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 07:38:30 +0000</pubDate>
		<dc:creator>Roberto van der Linden</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[CMS]]></category>
		<category><![CDATA[Hippo]]></category>
		<category><![CDATA[Kapow]]></category>
		<category><![CDATA[Migration]]></category>
		<category><![CDATA[Spring Framework]]></category>
		<category><![CDATA[Spring Integration]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://blog.jteam.nl/?p=1621</guid>
		<description><![CDATA[In one of the projects we need to migrate content from multiple websites into Hippo CMS. One of the interesting parts of this migration is that one of the websites will constantly provide us with updates of the content. Therefore it makes the migration a continuous process.
In this post I will explain how we use [...]]]></description>
			<content:encoded><![CDATA[<p>In one of the projects we need to migrate content from multiple websites into <a href="http://www.onehippo.org/cms7/" target="_blank">Hippo CMS</a>. One of the interesting parts of this migration is that one of the websites will constantly provide us with updates of the content. Therefore it makes the migration a continuous process.</p>
<p>In this post I will explain how we use Spring Integration to migrate content, handle errors, measure performance and deal with the fact that content could contain references to other content that is not imported yet.</p>
<p><span id="more-1621"></span></p>
<h2>Short Spring Integration introduction</h2>
<p>As I cannot explain Spring Integration in a few sentences, I will just focus on the elements that I use in the example. To get a complete overview of the elements I recommend you to read the reference manual.</p>
<ul>
<li><strong>Message</strong> – Generic container for data. It contains the payload which can be any object.</li>
<li><strong>Message Channel</strong> – Used for transporting the data between the different elements.</li>
<li><strong>ChannelAdapter</strong> &#8211; Message Endpoint that enables connecting a single sender or receiver to a channel.</li>
<li><strong>Transformer</strong> &#8211; Enables the loose-coupling of Message Producers and Message Consumers by transforming a message to another type.</li>
<li><strong>Service activator</strong> &#8211; The endpoint type for connecting any Spring-managed Object to an input channel so that it may play the role of a service.</li>
<li><strong>Router</strong> &#8211; Provides a simple way to connect a router to an input channel.</li>
<li><strong>Splitter</strong> &#8211; Partition a message in several parts, and send the resulting messages to be processed independently.</li>
</ul>
<h2>Getting the content</h2>
<p>Before you can start importing the content, you of course need to scrape the content from the different websites. In our case this is done by the guys from <a href="http://kapowtech.com/" target="_blank">Kapow</a>. They provide us with a lot content that is preformatted in XML files so that our import tool can handle the incoming requests. The content is distinguished by the type of document. So for example we could have news, address, a brochure and many more. The different types of documents contain data like images, videos, PDF files and of course text. Each XML file contains an element that represent a unique id for that file. This is used to identify any existing documents in the CMS.</p>
<h2>Connecting to the repository</h2>
<p>Hippo CMS is created on top of the <a href="http://jackrabbit.apache.org/" target="_blank">Apache Jackrabbit</a> repository. We connect directly to the repository using the Hippo Repository Connector that is provided in the Hippo Site Toolkit. This enables us to interact with the repository and provides us the possibility to perform actions like storing, editing and finding nodes.</p>
<p>My colleague Jettro Coenradie has written a <a href="http://www.gridshore.nl/2009/01/16/connecting-to-hippo-ecm-using-a-springframework-connector/" target="_blank">blog post</a> that goes more in-depth about connecting to the Hippo Repository.</p>
<h2>Process overview</h2>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/01/Springintegration1.jpg"><img style="display: inline; border-width: 0px;" title="Spring integration" src="http://blog.jteam.nl/wp-content/uploads/2010/01/Springintegration_thumb1.jpg" border="0" alt="Spring integration" width="503" height="619" /></a></p>
<h3>Starting point</h3>
<p>As you can see in the image we provide two ways for Kapow to deliver the content. One is via web services and the other one is directly via the file system (as Kapow runs its tool on the same server as the importer). This has few reasons:</p>
<ol>
<li>Web services provides more flexibility for other applications to connect with the importer tool.</li>
<li>Using the web service will prevent the problem that Spring Integration tries to read the file before it is completely written to the file system.</li>
<li>When the web service is not available, Kapow is still able to write the XML files directly to the file system.</li>
</ol>
<h3>Webservice</h3>
<p>Spring Integration provides us with a inbound web service gateway that send a message to a channel that is received from a Web Service invocation.</p>
<p>As you can see in the process overview image, messages that are received from the web service are enriched with the filename and then written to the file system. We have to do this in order to create an XML file (using the transformer) which obviously needs a filename. With the file outbound gateway the XML file is placed in the directory that is scanned for new files.</p>
<p>To make this all work we have to configure in the Spring WS servlet the endpoint mapping that know which request needs to map to our gateway that is configured in our integration context.</p>
<p>When the process is finished with writing to the file system and therefore correctly received by the importer we use a service activator that returns a ResponseMessage with the text “OK”. This response message is received by Kapow.</p>
<p>The endpoint configuration in the web service servlet:</p>
<pre class="brush: xml;">
    &lt;bean id=&quot;endpointMapping&quot; class=&quot;org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping&quot;&gt;
        &lt;property name=&quot;mappings&quot;&gt;
            &lt;props&gt;
                &lt;prop key=&quot;{http://www.jteam.nl/pons/webservice}AddressRequest&quot;&gt;webserviceGateway&lt;/prop&gt;
                &lt;prop key=&quot;{http://www.jteam.nl/pons/webservice}NewsRequest&quot;&gt;webserviceGateway&lt;/prop&gt;
            &lt;/props&gt;
        &lt;/property&gt;
    &lt;/bean&gt;
</pre>
<p>The integration configuration:</p>
<pre class="brush: xml;">
&lt;si-ws:inbound-gateway id=&quot;webserviceGateway&quot; marshaller=&quot;unmarshaller&quot; request-channel=&quot;transformedIncomingRequestBuffer&quot; /&gt;

&lt;si:channel id=&quot;transformedIncomingRequestBuffer&quot; /&gt;

&lt;si:transformer ref=&quot;headerEnricher&quot; output-channel=&quot;enrichedUnmarchalledInputFile&quot; input-channel=&quot;transformedIncomingRequestBuffer&quot; /&gt;
&lt;si:channel id=&quot;enrichedUnmarchalledInputFile&quot; /&gt;

&lt;si-xml:marshalling-transformer marshaller=&quot;unmarshaller&quot; output-channel=&quot;unmarchalledInputFile&quot; input-channel=&quot;enrichedUnmarchalledInputFile&quot; result-transformer=&quot;toStringTransformer&quot; /&gt;
&lt;si:channel id=&quot;unmarchalledInputFile&quot; /&gt;

&lt;file:outbound-gateway request-channel=&quot;unmarchalledInputFile&quot; reply-channel=&quot;handledFile&quot; delete-source-files=&quot;false&quot; directory=&quot;$si{file.import.path}&quot; /&gt;

&lt;si:channel id=&quot;handledFile&quot; /&gt;

&lt;si:service-activator ref=&quot;tempHandler&quot; input-channel=&quot;handledFile&quot; /&gt;

&lt;bean id=&quot;headerEnricher&quot; class=&quot;nl.jteam.importer.HeaderEnricher&quot; /&gt;
&lt;bean id=&quot;tempHandler&quot; class=&quot;nl.jteam.importer.ResponseMessageHandler&quot; /&gt;
</pre>
<h3>Transform file</h3>
<p>All the XML files are written to the file system in a given directory. With the inbound-channel-adapter element the files are read from the given directory. You can provide a filter that only accepts the types based on the known suffix. In our case the only files we want to read are XML files. The poller is used to configure how the maximum messages we want per poll and on what interval it needs to scan the directory for new files.</p>
<p>The file-to-string-transformer element transforms, as the name already suggests, a file to a string. This string is then used by the unmarshalling-transformer as input for the unmarshalling process to create JAXB objects.</p>
<pre class="brush: xml;">
&lt;file:inbound-channel-adapter id=&quot;fileAdapter&quot; directory=&quot;$si{file.import.path}&quot; filter=&quot;patternMatchingFileListFilter&quot; channel=&quot;fileInputChannel&quot;&gt;
    &lt;si:poller max-messages-per-poll=&quot;$si{file.poller.maxperpoll}&quot;&gt;
        &lt;si:interval-trigger time-unit=&quot;MILLISECONDS&quot; interval=&quot;$si{file.poller.interval}&quot; /&gt;:         &lt;si:interval-trigger time-unit=&quot;MILLISECONDS&quot; interval=&quot;$si{file.poller.interval}&quot; /&gt;
    &lt;/si:poller&gt;
&lt;/file:inbound-channel-adapter&gt;
&lt;si:channel id=&quot;fileInputChannel&quot; datatype=&quot;java.io.File&quot; /&gt;

&lt;file:file-to-string-transformer output-channel=&quot;xmlInputChannel&quot; input-channel=&quot;fileInputChannel&quot; charset=&quot;UTF-8&quot; delete-files=&quot;true&quot; /&gt;
&lt;si:channel id=&quot;xmlInputChannel&quot; /&gt;

&lt;si-xml:unmarshalling-transformer id=&quot;defaultUnmarshaller&quot; output-channel=&quot;docTypeChannel&quot; input-channel=&quot;xmlInputChannel&quot; unmarshaller=&quot;unmarshaller&quot; /&gt;

&lt;bean id=&quot;patternMatchingFileListFilter&quot; class=&quot;org.springframework.integration.file.PatternMatchingFileListFilter&quot;&gt;
    &lt;constructor-arg value=&quot;.*\.xml&quot; /&gt;
&lt;/bean&gt;

&lt;bean id=&quot;unmarshaller&quot; class=&quot;org.springframework.oxm.jaxb.Jaxb2Marshaller&quot;&gt;
    &lt;property name=&quot;marshallerProperties&quot;&gt;
        &lt;map value-type=&quot;java.lang.Boolean&quot; key-type=&quot;java.lang.String&quot;&gt;
            &lt;entry key=&quot;jaxb.formatted.output&quot; value=&quot;true&quot; /&gt;
        &lt;/map&gt;
    &lt;/property&gt;
    &lt;property name=&quot;contextPaths&quot;&gt;
        &lt;list&gt;
            &lt;value&gt;nl.jteam.importer.jaxb.news&lt;/value&gt;
            &lt;value&gt;nl.jteam.importer.jaxb.address&lt;/value&gt;
        &lt;/list&gt;
    &lt;/property&gt;
    &lt;property name=&quot;schemas&quot;&gt;
        &lt;list&gt;
            &lt;value&gt;classpath:/xsd/news.xsd&lt;/value&gt;
            &lt;value&gt;classpath:/xsd/address.xsd&lt;/value&gt;
        &lt;/list&gt;
    &lt;/property&gt;
&lt;/bean&gt;
</pre>
<h3>Document router</h3>
<p>To identify which handler class needs to handle the document that is being imported, we created a router. This router gets the name from the payload and returns this value. This value than can be used to determine the channel to put the message on. So when the name of the payload is <em>News </em>it will use the channel with id <em>News</em> to put the message on.</p>
<p>The configuration:</p>
<pre class="brush: xml;">
&lt;si:channel id=&quot;docTypeChannel&quot; /&gt;

&lt;si:router ref=&quot;docTypeRouter&quot; input-channel=&quot;docTypeChannel&quot; method=&quot;resolveObjectTypeChannel&quot; /&gt;
&lt;si:channel id=&quot;News&quot; /&gt;
&lt;si:channel id=&quot;Address&quot; /&gt;

&lt;si:service-activator ref=&quot;newsMessageHandler&quot; output-channel=&quot;newContentItemNotification&quot; input-channel=&quot;News&quot; method=&quot;handleMessage&quot; /&gt;
&lt;si:service-activator ref=&quot;addressMessageHandler&quot; output-channel=&quot;newContentItemNotification&quot; input-channel=&quot;Address&quot; method=&quot;handleMessage&quot; /&gt;

&lt;bean class=&quot;nl.jteam.importer.DocumentTypeMessageRouter&quot; name=&quot;docTypeRouter&quot; /&gt;
</pre>
<p>The implementation of the router class:</p>
<pre class="brush: java;">
public class DocumentTypeMessageRouter {

    public String resolveObjectTypeChannel(Message message) {
        return message.getPayload().getClass().getSimpleName();
    }
}
</pre>
<h3>Handlers</h3>
<p>Each document type has his own handler class. This class is responsible for handling all the properties that are relevant for that document.</p>
<p>A document in Hippo CMS is a JCR node in the repository. The handler will create this node if it not already exists. If it does exist it will take that node. Because the content from the XML is the correct content, all properties and child nodes will be removed. So any change that is made to the content via the CMS in that document will be gone. Because we keep the node, references in the repository by other nodes will be intact, but all properties will be recreated by the handler.</p>
<p>For each property the handler will add this to the node or calls another handler that handles that specific property such as an image handler or audio handler class.</p>
<p><strong>Missing links</strong></p>
<p>It could be that a document has references to another document that is not imported yet. This means that the link cannot be created yet. To solve this problem we store for each link that cannot be created a missing link node in the repository. This node contains the information that is necessary to create the link when that document is imported. I will explain later on how the missing links are used when updating content.</p>
<p>When the handler is finished with creating a document in Hippo CMS, it will execute a query that finds all the documents that contain a reference to the imported document or in other words, it will find all missing links that now can be resolved.</p>
<h3>Referred documents splitter</h3>
<p>The outcome of the query that looks for references to the imported document could return multiple documents of different types. For example, we have imported an address document and that document is referenced by a news item and a press release item. These two documents will each be represented in a ReferredDefinition object. These ReferredDefinition objects contain the information of the missing link node plus the unique repository id (uuid) of the currently imported document.</p>
<p>Spring Integration provides us a splitter that has the capability to partition the message in several messages. The implementation of our splitter receives a list of ReferredDefinition objects. Each message (ReferredDefinition object) will be send to a router that routes the ReferredDefinition object to his appropriate channel.</p>
<p>The configuration:</p>
<pre class="brush: xml;">
&lt;si:channel id=&quot;newContentItemNotification&quot; /&gt;

&lt;si:splitter ref=&quot;referredBySplitter&quot; output-channel=&quot;referedBy&quot; input-channel=&quot;newContentItemNotification&quot; method=&quot;splitReferredDefinitions&quot; /&gt;

&lt;bean class=&quot;nl.jteam.importer.ReferredByMessageSplitter&quot; name=&quot;referredBySplitter&quot; /&gt;
</pre>
<p>The referred by message splitter class:</p>
<pre class="brush: java;">
public class ReferredByMessageSplitter {

    public List&lt;referreddefinition&gt; splitReferredDefinitions(List&lt;referreddefinition&gt; referedDefinitions) {
        return referredDefinitions;
    }
}
</pre>
<h3>Referred by router</h3>
<p>The splitter provides the router with a single ReferredDefinition item. The ReferredDefinition object contains information about the document type that needs to be updated. The implementation of the router is quite simple. It gets the type of the document that needs to be updated and adds the string “Update” to the document type. This combination gives us the name of the channel that is used to put the message on.</p>
<p>The configuration:</p>
<pre class="brush: xml;">
&lt;si:channel id=&quot;referredBy&quot; /&gt;
&lt;si:router ref=&quot;referredByRouter&quot; input-channel=&quot;referredBy&quot; method=&quot;resolveItemChannel&quot; /&gt;

&lt;si:channel id=&quot;NewsUpdate&quot; /&gt;
&lt;si:channel id=&quot;PressReleaseUpdate&quot; /&gt;

&lt;bean class=&quot;nl.jteam.importer.ReferredByMessageRouter&quot; name=&quot;referredByRouter&quot; /&gt;
</pre>
<p>The referred by message router class:</p>
<pre class="brush: java;">
public class ReferredByMessageRouter {

    public String resolveItemChannel(ReferredDefinition referredDefinition) {
        return referredDefinition.getPrimaryTypeReferredBy() + &quot;Update&quot;;
    }
}
</pre>
<h3><span style="color: #ff0000;"> </span></h3>
<h3>Update handlers</h3>
<p>Each document type has just like the normal handlers his own update handler. The update handlers are used for updating content that has a reference to the imported document. The handler receives in ReferredDefinition object which contains the information of the document that contains the reference.</p>
<p><a href="http://blog.jteam.nl/wp-content/uploads/2010/01/update1.jpg"><img style="display: inline; border-width: 0px;" title="update" src="http://blog.jteam.nl/wp-content/uploads/2010/01/update_thumb1.jpg" border="0" alt="update" width="353" height="205" /></a></p>
<p>So if we have for example two documents (A and B). B is a news item that contains a field addres and A is an address document. Document B is already imported and has a reference to A. Document B links to document A, but because A was not imported yet, a missing link node for A exists. Now document A is going to be imported, so document B can be updated with a working link. The content handler of A finds the missing link and creates a ReferredDefinition object with the information of the missing link. The update handler finds document B based on his unique id that is also stored in the ReferredDefinition object.</p>
<p>Now that document B is found, the update handler can add the correct property (which is specified in the ReferredDefinition object) to document B with the link to document A. When the link is created, it is no longer necessary to keep the missing link node and will therefore be removed.</p>
<h3>Error handling</h3>
<p>When importing content errors could occur. We distinguish between two types of errors:</p>
<ol>
<li>Critical errors &#8211; Something is wrong with the XML structure or with the connection to the repository.</li>
<li>Non critical errors – Errors like incorrect content or links that cannot be created.</li>
</ol>
<p>When a critical error occurs it means that we cannot import that document at this moment. So we have defined an error channel that is used to put the payload on and transform it back to an XML file. That file is than written to a different  folder, so that it will not be picked up again by Spring Integration.</p>
<p>With non critical errors it is only necessary to notify a system admin that something went wrong. So in order to do this, we introduced an error collector. This error collector is nothing more than object that contains a list of errors and a little information about the document. This collector is passed through the whole process of importing a document and all errors that occur will be collected. At the end of that process the errors will be mailed to the system admin. Currently this is done after each document, but this will probably change in the future to use some sort of batch mailing.</p>
<pre class="brush: xml;">
&lt;si:channel id=&quot;errorChannel&quot; /&gt;

&lt;si:chain input-channel=&quot;errorChannel&quot;&gt;
    &lt;si:service-activator ref=&quot;errorMessageHandler&quot; method=&quot;handleMessage&quot; /&gt;
    &lt;si:router ref=&quot;errorMessageRouter&quot; method=&quot;routeByPayloadType&quot; /&gt;
&lt;/si:chain&gt;

&lt;si:channel id=&quot;errorOutputChannel&quot; /&gt;
&lt;si-xml:marshalling-transformer id=&quot;defaultMarshaller&quot; marshaller=&quot;unmarshaller&quot; output-channel=&quot;xmlOutputChannel&quot; input-channel=&quot;errorOutputChannel&quot; result-transformer=&quot;toStringTransformer&quot; /&gt;

&lt;bean id=&quot;toStringTransformer&quot; class=&quot;org.springframework.integration.xml.transformer.ResultToStringTransformer&quot; /&gt;

&lt;si:channel id=&quot;xmlOutputChannel&quot; /&gt;

&lt;file:outbound-channel-adapter directory=&quot;$si{file.unhandled.path}&quot; channel=&quot;xmlOutputChannel&quot; /&gt;

&lt;bean id=&quot;errorMessageHandler&quot; class=&quot;nl.jteam.importer.errorhandling.ErrorHandler&quot;&gt;
    &lt;property name=&quot;errorMailer&quot; ref=&quot;errorMailer&quot;&gt;&lt;/property&gt;
&lt;/bean&gt;

&lt;bean id=&quot;errorMessageRouter&quot; class=&quot;nl.jteam.importer.errorhandling.ErrorMessageRouter&quot;&gt;
    &lt;property name=&quot;objectChannel&quot; ref=&quot;errorOutputChannel&quot;&gt;&lt;/property&gt;
    &lt;property name=&quot;xmlChannel&quot; ref=&quot;xmlOutputChannel&quot;&gt;&lt;/property&gt;
&lt;/bean&gt;
</pre>
<h3>Performance</h3>
<p>With the use of an aspect we send a message to the <em>performanceMonitor</em> channel. When you declare a MessageChannel you can call the method send(..) to send your message to the channel. In our case we create a new StringMessage to send the performance message. The channel is used by the service-activator. The service-activator uses a poller to throttle inbound messages.</p>
<p>The service-activator passes the message to the Log4jMonitorPersister, where it logs the message.</p>
<p>The configuration:</p>
<pre class="brush: xml;">
&lt;si:channel id=&quot;performanceMonitor&quot;&gt;
    &lt;si:queue /&gt;
&lt;/si:channel&gt;

&lt;si:service-activator ref=&quot;monitorPersister&quot; input-channel=&quot;performanceMonitor&quot; method=&quot;persist&quot;&gt;
    &lt;si:poller max-messages-per-poll=&quot;100&quot;&gt;
        &lt;si:interval-trigger time-unit=&quot;MILLISECONDS&quot; interval=&quot;10000&quot; /&gt;
    &lt;/si:poller&gt;
&lt;/si:service-activator&gt;

&lt;bean id=&quot;monitorPersister&quot; class=&quot;nl.jteam.importer.monitoring.Log4jMonitorPersister&quot; /&gt;

&lt;aop:aspectj-autoproxy /&gt;

&lt;bean id=&quot;monitoringHandlersAdvice&quot; class=&quot;nl.jteam.importer.monitoring.MonitoringHandlersAdvice&quot;&gt;
    &lt;property name=&quot;performanceMonitor&quot; ref=&quot;performanceMonitor&quot;&gt;&lt;/property&gt;
&lt;/bean&gt;
</pre>
<p>The MonitoringHandlersAdvice class:</p>
<pre class="brush: java;">
@Aspect
public class MonitoringHandlersAdvice {

    private MessageChannel channel;

    @Around(&quot;execution(* nl.jteam.importer.handler.*Handler.handleMessage(..)) &amp;&amp; args(message)&quot;)
    public Object monitorB(ProceedingJoinPoint proceedingJoinPoint, Message message)
            throws Throwable {
        String fileName = (String) message.getHeaders().get(&quot;springintegration_file_name&quot;);
        Object payload = message.getPayload();

        StopWatch clock = new StopWatch();
        DateTime start = new DateTime();

        try {
            clock.start(proceedingJoinPoint.toShortString());
            return proceedingJoinPoint.proceed(new Object[]{message});
        } finally {
            clock.stop();
            StringBuilder outMessageBuilder = new StringBuilder();
            outMessageBuilder.append(clock.getTotalTimeMillis()).append(&quot;;&quot;)
                    .append(payload.getClass().getSimpleName()).append(&quot;;&quot;)
                    .append(fileName).append(&quot;;&quot;)
                    .append(start.toString(&quot;yyyy-MM-dd HH:mm:ss&quot;));
            channel.send(new StringMessage(outMessageBuilder.toString()));
        }
    }

    @Required
    public void setPerformanceMonitor(MessageChannel performanceMonitor) {
        channel = performanceMonitor;
    }
}
</pre>
<p>The Log4jMonitorPersister class:</p>
<pre class="brush: java;">
public class Log4jMonitorPersister implements MonitorPersister {
    private final static Logger log = LoggerFactory.getLogger(MonitorPersister.class);

    @Override
    public void persist(String monitorEvent) {
        log.info(monitorEvent);
    }
}
</pre>
<h2>Conclusion</h2>
<p>I have showed you how we use Spring Integration to migrate XML content to Hippo CMS. As you could see the configuration is relatively simple and when we want to import a new content type, all we have to do is create a handler and wire up the configuration. As always SpringSource provides good documentation that makes is easy work with Spring Integration.</p>
<h2>References</h2>
<p style="text-align: left;"><strong>Spring Integration: <a title="http://static.springsource.org/spring-integration/reference/htmlsingle/spring-integration-reference.html" href="http://static.springsource.org/spring-integration/reference/htmlsingle/spring-integration-reference.html">http://static.springsource.org/spring-integration/reference/htmlsingle/spring-integration-reference.html</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jteam.nl/2010/01/13/migrating-content-with-spring-integration-a-real-life-example/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
