<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:posterous="http://posterous.com/help/rss/1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
  <channel>
    <title>xenji.com</title>
    <link>http://xenji.com</link>
    <description>Developer Blog</description>
    <generator>posterous.com</generator>
    <link xmlns="http://www.w3.org/2005/Atom" href="http://posterous.com/api/sup_update#407644e9c" type="application/json" rel="http://api.friendfeed.com/2008/03#sup" />
    
    
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/xenjicom" /><feedburner:info uri="xenjicom" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://posterous.superfeedr.com/" /><item>
      <pubDate>Sun, 15 Jan 2012 01:59:00 -0800</pubDate>
      <title>Parallel "mv" with Google Go</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/YbSEKe3fdr8/parallel-mv-with-google-go</link>
      <guid isPermaLink="false">http://xenji.com/parallel-mv-with-google-go</guid>
      <description>&lt;p&gt;
	&lt;p&gt;The first question, that might come into you mind, could be "why the heck should I do a parallel "mv""? The answer is quite easy: Imagine you have a bunch of folders that you unpack and move to a specific location - &amp;nbsp;your http document root. Those folders are dependend on each other, using php files via include or require, etc. You need to move them consitently as "the new release" to their destination. You might ask, why the normal linux "mv" is not enough, even when combining the call with "&amp;amp;&amp;amp;"? Imagine that the webserver has a normal traffic of over 1000 page impressions per second. How big is the timeframe you have for moving the folders without having an inconsistent state? The answer is heavy to guess or to calculate. With a transfer time of ~1 msec you hit the 1% rate of getting a request for a page with an inconsistent state. The more you get under the 1 msec mark, the better it is.&lt;/p&gt;
&lt;p&gt;The parallel version, which uses Goroutines - a threading model that is even more lightweight than posix threads - does a move of two folders in ~0.019 msec. This reduces the chance of failure under 1%, even under 0.2%.&lt;/p&gt;
&lt;p&gt;As we use it for our release process, the folders are compiled in the binary. This is not very flexible, but prevents typos or human failure while using it.&lt;/p&gt;
&lt;p&gt;As posterous does not like my embedded code, please find it here&amp;nbsp;&lt;div class="data type-go"&gt;
      &lt;table class="lines" cellspacing="0" cellpadding="0"&gt;
        &lt;tr&gt;
          &lt;td&gt;
            &lt;pre class="line_numbers"&gt;&lt;span rel="#L1" id="L1"&gt;1&lt;/span&gt;
&lt;span rel="#L2" id="L2"&gt;2&lt;/span&gt;
&lt;span rel="#L3" id="L3"&gt;3&lt;/span&gt;
&lt;span rel="#L4" id="L4"&gt;4&lt;/span&gt;
&lt;span rel="#L5" id="L5"&gt;5&lt;/span&gt;
&lt;span rel="#L6" id="L6"&gt;6&lt;/span&gt;
&lt;span rel="#L7" id="L7"&gt;7&lt;/span&gt;
&lt;span rel="#L8" id="L8"&gt;8&lt;/span&gt;
&lt;span rel="#L9" id="L9"&gt;9&lt;/span&gt;
&lt;span rel="#L10" id="L10"&gt;10&lt;/span&gt;
&lt;span rel="#L11" id="L11"&gt;11&lt;/span&gt;
&lt;span rel="#L12" id="L12"&gt;12&lt;/span&gt;
&lt;span rel="#L13" id="L13"&gt;13&lt;/span&gt;
&lt;span rel="#L14" id="L14"&gt;14&lt;/span&gt;
&lt;span rel="#L15" id="L15"&gt;15&lt;/span&gt;
&lt;span rel="#L16" id="L16"&gt;16&lt;/span&gt;
&lt;span rel="#L17" id="L17"&gt;17&lt;/span&gt;
&lt;span rel="#L18" id="L18"&gt;18&lt;/span&gt;
&lt;span rel="#L19" id="L19"&gt;19&lt;/span&gt;
&lt;span rel="#L20" id="L20"&gt;20&lt;/span&gt;
&lt;span rel="#L21" id="L21"&gt;21&lt;/span&gt;
&lt;span rel="#L22" id="L22"&gt;22&lt;/span&gt;
&lt;span rel="#L23" id="L23"&gt;23&lt;/span&gt;
&lt;/pre&gt;
          &lt;/td&gt;
          &lt;td width="100%"&gt;
                &lt;div class="highlight"&gt;&lt;pre /&gt;&lt;div class="line" id="LC1"&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;os&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;runtime&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC6"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;aFromList&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/tmp/checkout/folder1_new&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/tmp/checkout/folder2_new&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;aToList&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/var/www/folder1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/var/www/folder2&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC8"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC9"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC10"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC11"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC12"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="p"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;aFromList&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC13"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;aToList&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC14"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC15"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC16"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="p"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC17"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC18"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC19"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC20"&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="nb"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC21"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC22"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC23"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;
          &lt;/td&gt;
        &lt;/tr&gt;
      &lt;/table&gt;
  &lt;/div&gt;&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/parallel-mv-with-google-go"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/parallel-mv-with-google-go#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/YbSEKe3fdr8" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/parallel-mv-with-google-go</feedburner:origLink></item>
    <item>
      <pubDate>Mon, 19 Dec 2011 21:43:00 -0800</pubDate>
      <title>A few reasons why we do not need meta languages...</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/SLkcI2d6mng/a-few-reasons-why-we-do-not-need-meta-languag</link>
      <guid isPermaLink="false">http://xenji.com/a-few-reasons-why-we-do-not-need-meta-languag</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Just for the trolls: This is no bashing of the articles about &lt;a href="http://lesscss.org/"&gt;less&lt;/a&gt;, &lt;a href="http://sass-lang.com/"&gt;sass&lt;/a&gt;, &lt;a href="http://haml-lang.com/"&gt;haml&lt;/a&gt;, &lt;a href="http://jashkenas.github.com/coffee-script/"&gt;coffeescript&lt;/a&gt;, etc. Especially &lt;a href="http://blog.mayflower.de/archives/802-09.12.-10-good-reasons-why-to-learn-a-css-meta-language-like-sass-or-less.html" target="_blank"&gt;the one I've read on Mayflower's blog&lt;/a&gt;&amp;nbsp;is very true.&lt;/p&gt;
&lt;p&gt;But!&amp;nbsp;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;span style="color: #555555; font-family: helvetica, arial, freesans, clean, sans-serif; line-height: 20px; background-color: #f8f8f8;"&gt;A language that doesn't change the way you think about programming is not worth learning.&amp;mdash; Alan Perlis&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;span style="font-family: helvetica, arial, freesans, clean, sans-serif; line-height: 20px; background-color: #f8f8f8; color: #000000;"&gt;And I think Alan is right. None of the languages mentioned above changes the way you think about the language it "generates". The only thing you change, is the way you write stuff in shorter, maybe more oop-ish or whatever style. But does it change the way we think about HTML &amp;amp; CSS? As long as people still addicted to table layouts, we might have more important problems than just writing less code, don't we?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: helvetica, arial, freesans, clean, sans-serif; line-height: 20px; background-color: #f8f8f8; color: #000000;"&gt;I did not met any - pure - HTML/CSS guy/gal yet, who ever said, that haml, sass or less did the right job for him/her. Only the PHP and Ruby guys and gals who are forced to write stylesheets love this style of writing. And by the way: As we generate HTML strings with PHP, why don't we use the same cool technology to generate CSS in a proper way? We (the PHP world) have invented a thousand ways to abstract and instrument the generation of websites (which means HTML - just wanted to mention it ;) ), that we need another two or three ways to generate some other text (CSS, JavaScript, ...)?&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: helvetica, arial, freesans, clean, sans-serif; line-height: 20px; background-color: #f8f8f8; color: #000000;"&gt;Let me take something from "&lt;a href="http://www.python.org/dev/peps/pep-0020/"&gt;the zen of python&lt;/a&gt;" for a quote:&lt;/span&gt;&lt;/p&gt;
&lt;blockquote class="posterous_short_quote"&gt;
&lt;p&gt;There should be one-- and preferably only one --obvious way to do it.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For me, the obivous way to do it is "use the weapons at hand", use your well known language (PHP, Ruby, Python ... whatever it might be).&lt;/p&gt;
&lt;p&gt;&lt;span style="background-color: #f8f8f8; font-family: helvetica, arial, freesans, clean, sans-serif; line-height: 20px;"&gt;Just for my information: Is there anyone out there who does HTML/CSS only (no PHP, no RoR or whatever) and uses haml, sass and/or less?&lt;/span&gt;&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/a-few-reasons-why-we-do-not-need-meta-languag"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/a-few-reasons-why-we-do-not-need-meta-languag#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/SLkcI2d6mng" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/a-few-reasons-why-we-do-not-need-meta-languag</feedburner:origLink></item>
    <item>
      <pubDate>Thu, 24 Nov 2011 22:58:54 -0800</pubDate>
      <title>Dependency Injection mit in PHP mit Any\Di/</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/NuaMwPp8BR4/dependency-injection-mit-in-php-mit-anydi</link>
      <guid isPermaLink="false">http://xenji.com/dependency-injection-mit-in-php-mit-anydi</guid>
      <description>&lt;p&gt;
	&lt;p&gt;&lt;a href="http://twitter.com/timglabisch" target="_blank"&gt;Tim Glabisch&lt;/a&gt; und ich durften auf gestrigen PHPUG D/DU/KR Veranstaltung einen Vortrag zum Thema Dependency Injection halten. Tim und ich haben uns die Pr&amp;auml;sentation aufgeteilt, der Eine hat ein wenig &amp;uuml;ber das Pattern und den Architektur Ansatz gesprochen, der Andere hat einen DI-Container vorgestellt.&lt;/p&gt;
&lt;p&gt;Tim war so nett seinen eigenen DIC vorzustellen: "&lt;a href="http://anydi.ainfach.de/" target="_blank"&gt;Any\Di&lt;/a&gt;". Any\Di erinnert, f&amp;uuml;r die Leute, die sich auch mal mit Java besch&amp;auml;ftigen, an Google Guice - auch wenn es kein direkter Port von Guice ist.&lt;/p&gt;
&lt;p&gt;Die Benutzung von Any\Di ist recht einfach (worin meiner Meinung nach auch gleichzeitig die gr&amp;ouml;&amp;szlig;te Macht steckt). Die Beispiele sind von den Tutorial Seiten von Tim "ausgeliehen" ;).&lt;/p&gt;
&lt;p&gt;Man hat einer Seits die M&amp;ouml;glichkeit seine Dependencies programmatisch zu deklarieren. Any\Di nennt das "bind":&lt;/p&gt;
&lt;p&gt;&lt;code&gt;di();&lt;/code&gt;&lt;br /&gt; &lt;code&gt;$di-&amp;gt;bind('\de\any\di\test\example\basics\iLogger')&lt;br /&gt;-&amp;gt;to('\de\any\di\test\example\basics\Logger');&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Wir binden also ein Interface an eine konkrete Implementierung. &amp;Uuml;ber ein&amp;nbsp; &lt;code&gt;$di-&amp;gt;get('\de\any\di\test\example\basics\iLogger');&lt;/code&gt; Komme ich nun auch wieder an die dem Interface folgende Instanz heran. Ich kann nur empfehlen es sich mal anzuschauen, Tim freut sich auf Feedback!&lt;/p&gt;
&lt;p&gt;Hier sind noch die Prezi Slides von gestern:&lt;/p&gt;
&lt;div class="prezi-player"&gt;
&lt;object height="400" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="480"&gt;
&lt;param name="movie" value="http://prezi.com/bin/preziloader.swf" /&gt;
&lt;param name="allowfullscreen" value="true" /&gt;
&lt;param name="allowscriptaccess" value="always" /&gt;
&lt;param name="bgcolor" value="#ffffff" /&gt;
&lt;param name="flashvars" value="prezi_id=zijnwebmohfx&amp;amp;lock_to_path=1&amp;amp;color=ffffff&amp;amp;autoplay=no&amp;amp;autohide_ctrls=0" /&gt;&lt;embed src="http://prezi.com/bin/preziloader.swf" type="application/x-shockwave-flash" height="400" flashvars="prezi_id=zijnwebmohfx&amp;amp;lock_to_path=1&amp;amp;color=ffffff&amp;amp;autoplay=no&amp;amp;autohide_ctrls=0" width="480"&gt;&lt;/embed&gt;
&lt;/object&gt;
&lt;div class="prezi-player-links"&gt;
&lt;p&gt;&lt;a href="http://prezi.com/zijnwebmohfx/dependency-injection/" title="                                                          No description                                                      "&gt;dependency injection&lt;/a&gt; on &lt;a href="http://prezi.com"&gt;Prezi&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/dependency-injection-mit-in-php-mit-anydi"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/dependency-injection-mit-in-php-mit-anydi#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/NuaMwPp8BR4" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/dependency-injection-mit-in-php-mit-anydi</feedburner:origLink></item>
    <item>
      <pubDate>Thu, 10 Nov 2011 03:43:00 -0800</pubDate>
      <title>Trouble um MongoDB</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/XX96zjH0Ho0/trouble-um-mongodb</link>
      <guid isPermaLink="false">http://xenji.com/trouble-um-mongodb</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Was ist nur los im Social Web? &lt;a href="http://pastebin.com/raw.php?i=FD3xe6Jt" target="_blank"&gt;MongoDB wurde r&amp;uuml;de von einem Unbekannten attakiert&lt;/a&gt;, der &lt;a href="http://news.ycombinator.com/item?id=3202081" target="_blank"&gt;CTO von 10gen antwortet &amp;uuml;ber ycombinator&lt;/a&gt;. Im Verlauf der Kommentare meldet sich dann auch der der angeblich urspr&amp;uuml;ngliche Autor zu Wort und konstatiert, dass es sich um einen Hoax handelt.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Verwirrt? Ich auch. Liest man allerdings brav weiter, dann erf&amp;auml;hrt man, dass es sich um zwei Autoren handelt. nmongo und nomoremongo. Der Eine ist ein &lt;span style="text-decoration: line-through;"&gt;Troll&lt;/span&gt;&amp;nbsp;&lt;a href="http://twitter.com/#!/TomSCHnet/status/134294199959957504" target="_blank"&gt;Internetnutzer mit Frustrationshintergrund&lt;/a&gt;, der Andere der tats&amp;auml;chliche Autor des Pastbin-Textes. Auf Grund der Anonymit&amp;auml;t sind etliche Kommentarautoren skeptisch, was die Verwertbarkeit und den Wahrheitsgehalt der Aussagen angeht. Er verspricht jedoch die Ver&amp;ouml;ffentlichung seines Names nach der Aufl&amp;ouml;sung der Vertr&amp;auml;ge mit 10gen.&lt;/p&gt;
&lt;p&gt;Hat MongoDB wirklich diese Art von grunds&amp;auml;tzlichen Problemen, dann haben die New York Times, GitHub, Sourceforge, &lt;a href="http://www.slideshare.net/jorgeortiz85/mongosf-mongodb-foursquare" target="_blank"&gt;Foursquare&lt;/a&gt; und &lt;a href="http://www.slideshare.net/ibwhite/how-business-insider-uses-mongodb" target="_blank"&gt;BusinessInsider&lt;/a&gt;&amp;nbsp;sie auch. Alle genannten Firmen setzen nach eigener Aussage auf MongoDB - wo ich entsprechende Slides gefunden habe sind diese verlinkt.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Es bleibt spannend.&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/trouble-um-mongodb"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/trouble-um-mongodb#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/XX96zjH0Ho0" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/trouble-um-mongodb</feedburner:origLink></item>
    <item>
      <pubDate>Tue, 08 Nov 2011 02:24:00 -0800</pubDate>
      <title>Zarafa, z-push und iOS5</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/Y8XvibEkvqg/zarafa-z-push-und-ios5</link>
      <guid isPermaLink="false">http://xenji.com/zarafa-z-push-und-ios5</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Meine Migration von meinem Hosted-Exchange zu &lt;a href="http://www.zarafa.com/" target="_blank"&gt;Zarafa&lt;/a&gt; ist nun endlich komplett. Leider gab es da noch ein Problem mit &lt;a href="http://z-push.sourceforge.net/" target="_blank"&gt;z-push&lt;/a&gt; - einer in PHP geschriebenen ActiveSync Implementierung - und meinem iPhone mit iOS 5. Tante Google spuckt dazu einen &lt;a href="http://z-push.sourceforge.net/phpbb/viewtopic.php?f=7&amp;amp;t=1618" target="_blank"&gt;Forenthread&lt;/a&gt; aus, der ein Downgrade auf die Version 1.4.3 empfiehlt sowie einige Modifikationen an den Sourcen. Ich habe das mal ausprobiert und kann sagen ... ja, es l&amp;auml;uft, aber! Bei mir gingen leider die Umlaute nicht mehr. Zarafa's Webaccess zeigt mir Diese wunderbar an, das iPhone wandelt &amp;uuml;,&amp;ouml;,&amp;auml; und &amp;szlig; leider in "?" um. Schei&amp;szlig; Encoding. Die Version 1.5.5, also die aktuelle Stable, lief zuerst garnicht.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Die L&amp;ouml;sung ist einfacher als gedacht. Ich hatte zuerst keine SSL Verschl&amp;uuml;sselung f&amp;uuml;r den ActiveSync Endpoint eingerichtet, da ich das Setup nur testen wollte. Leider hielt genau dies die Version 1.5.5 davon ab ihren Dienst zu tun. Mit einem Snake-Oil Zertifikat l&amp;auml;uft die Version 1.5.5 auch mit iOS5 einwandfrei. Alle mit der Version 1.4.3 beschriebenen Probleme (Sync der Mails kann nicht mehr als eine Woche zur&amp;uuml;ck vollzogen werden, gel&amp;ouml;schte Mail werden nicht wirklich gel&amp;ouml;scht, Push oder CalDav laufen nicht korrekt) kann ich mit dieser Version nicht nachvollziehen. Ebenso das Umlautproblem hat sich erledigt.&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/zarafa-z-push-und-ios5"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/zarafa-z-push-und-ios5#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/Y8XvibEkvqg" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/zarafa-z-push-und-ios5</feedburner:origLink></item>
    <item>
      <pubDate>Sat, 05 Nov 2011 09:10:44 -0700</pubDate>
      <title>Sehr geehrte Headhunter, liebe Personalvermittler</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/3DFDoy_k7bc/sehr-geehrte-headhunter-liebe-personalvermitt</link>
      <guid isPermaLink="false">http://xenji.com/sehr-geehrte-headhunter-liebe-personalvermitt</guid>
      <description>&lt;p&gt;
	aus aktuellem Anlass und in der Hoffnung, dass ihr - neben meinem Xing Profil - auch meinen Blog lest, schreibe ich euch diese Zeilen. Ich habe zum Anfang September den Job gewechselt, das habt ihr sicherlich bemerkt. Ich gehe zwar nicht davon aus, dass ihr es in eure "sprech ich ihn jetzt an?"-&amp;Uuml;berlegung einbezieht, aber ich wollte in meiner grenzenlosen Naivit&amp;auml;t trotzdem mal darauf aufmerksam machen. Ich frage mich manches Mal ernsthaft, ob ihr nicht lieber h&amp;auml;ttet weiter euren gelernten Beruf weiter aus&amp;uuml;ben sollen. Vielleicht wart ihr ja gut darin? Und selbst wenn ihr diesen Beruf gelernt habt, scheinen die Meisten doch wo anders besser aufgehoben. Die Ignoranz, mit der ihr jedoch &amp;uuml;ber mich und mein &amp;ouml;ffentliches Profil herfallt, kennt leider kaum eine Grenze. Warum hat euch keiner beigebracht Profile auch mal zu interpretieren, nicht nur zu lesen? Selbst Google reagiert besser auf Keywords als ihr! Nur weil ich "XYZ" in meinem Profil stehen habe, seht ihr die Chance mich zum Experten zu erheben und in euer Suchprofil zu pressen? Ich bin gerade von einer Agentur zu einem v&amp;ouml;llig anders strukturierten Unternehmen gewechselt. Habt ihr mal nachgedacht, ob das vielleicht ... Absicht war? W&amp;uuml;rde ich in eine Agentur wollen, h&amp;auml;tte ich nicht dann auch eine Agentur gew&amp;auml;hlt? Meint ihr ernsthaft, ich wechsle nach nicht mal zwei Monaten direkt wieder den Job? Kennt ihr das Wort "Treue" oder auch "Nachhaltigkeit"? W&amp;auml;re es euch nicht genauso wichtig, dass ein Mitarbeiter in dem Unternehmen bleibt, an den ihr in vermittelt? Nunja, die Erwartungshaltung, dass Psychologie oder auch nur grunds&amp;auml;tzliches analytisches Verhalten in eure Arbeit mit einflie&amp;szlig;t, ist wohl doch zu viel erwartet, schlie&amp;szlig;lich ist der Mensch eure Ware und Nachhaltigkeit nicht euer Problem. Leider wandelt sich euer Verhalten mehr und mehr zu dem eines Spam-Bots und meine Reaktion darauf entspricht auch immer mehr diesem Schema - leider gibt es bei Xing noch keinen Spamfilter. Pers&amp;ouml;nliche Ansprachen sind selten geworden, die Stiefelleckerei in euren Texten und eure Penetranz kotzen mich an. Die Zeiten, wo ihr Nerds und Geeks mit Schmeicheleien hinterm Ofen hervor locken konntet, sind nun seit Jahren vorbei.

Ich suche mir meinen Job selbst aus. Und das habe ich bereits getan.

&lt;em&gt;Ich wei&amp;szlig;, dass ich einigen Vertretern eurer Zunft Unrecht antue. Leider sind mir bis zum heutigen Tage nur ein oder zwei von euch begegnet, von denen ich das oben gesagte nicht behaupten kann.&lt;/em&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/sehr-geehrte-headhunter-liebe-personalvermitt"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/sehr-geehrte-headhunter-liebe-personalvermitt#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/3DFDoy_k7bc" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/sehr-geehrte-headhunter-liebe-personalvermitt</feedburner:origLink></item>
    <item>
      <pubDate>Fri, 04 Nov 2011 12:59:00 -0700</pubDate>
      <title>Ein Newsletter Tool selbst gebaut - Neo4J, RabbitMQ, Vaadin</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/u9wKnNo-83U/ein-newsletter-tool-selbst-gebaut-neo4j-rabbi</link>
      <guid isPermaLink="false">http://xenji.com/ein-newsletter-tool-selbst-gebaut-neo4j-rabbi</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Seit einiger Zeit arbeite ich jetzt als Java Developer bei der&amp;nbsp;&lt;a href="http://www.trivago.de/" target="_blank"&gt;trivago GmbH&lt;/a&gt;.&amp;nbsp;Zum ersten Mal durfte ich nun auch an den trivago Developer Days teilnehmen, welche vom Konzept her etwas an die &lt;a href="http://www.google.com/jobs/lifeatgoogle/englife/index.html"&gt;Google'sche 20% Regelung&lt;/a&gt; erinnern. Wir Developer bekommen in regelm&amp;auml;&amp;szlig;igen Abst&amp;auml;nden 3-4 Tage Zeit, sich ein Projekt auszuw&amp;auml;hlen (aus dem internen Ideenportal oder aus eigener Motivation) und dieses Umzusetzen.  F&amp;uuml;r mein erstes DevDays Projekt habe ich mich, zusammen mit &lt;a href="http://www.redbrick.de/"&gt;Christian Krause&lt;/a&gt; (&lt;a href="http://twitter.com/#!/redbrick" target="_blank"&gt;@redbrick&lt;/a&gt;) an ein Mail Delivery System gesetzt. Drei Tage (plus ein Halber f&amp;uuml;r das Vorbereiten der Pr&amp;auml;sentation und ein weiterer Halber f&amp;uuml;r das Setup) sind nun nicht viel, auch wenn man die Definition von "Tag" irgendwo zwischen acht und 14 Stunden ansiedeln kann. Wir haben uns also auf die Kern-Features beschr&amp;auml;nkt, die wir selbst von einem solchen System erwarten w&amp;uuml;rden.  Klar war, dass Mail-Delivery die Kernkompetenz sein sollte. Wir wollten jedoch, auf der Delivery Schicht basierend, auch eine Applikation erstellen, damit der Nicht-Tekkie auch etwas davon hat. So ist die Idee des Newsletter Systems entstanden, welchem wir den Arbeitstitel Mail-Pigeon verpasst haben.  Die Wunsch-Features im &amp;Uuml;berblick:  Mail-Delivery:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Versand &amp;uuml;ber mehrere Clients (horiz. Skalierbarkeit)&lt;/li&gt;
&lt;li&gt;Kein Datenverlust beim Absturz einer oder aller Sending-Daemons&lt;/li&gt;
&lt;li&gt;Bounce Handling (zumindest erst mal rudiment&amp;auml;r)&lt;/li&gt;
&lt;li&gt;Ein Datenformat, dass sowohl von PHP und JavaScript, als auch von Java beherrscht wird. Bleibt nicht viel: XML und JSON. Und XML war es nicht ;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Newsletter System:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Absender Management (Durch die vielen Nationen und Sprachen bei trivago haben wir sehr verschiedene Absender)&lt;/li&gt;
&lt;li&gt;Empf&amp;auml;nger und Empf&amp;auml;ngergruppen&lt;/li&gt;
&lt;li&gt;Newsletter und Vorlagen f&amp;uuml;r neue Newsletter sowie Personalisierungsm&amp;ouml;glichkeiten&lt;/li&gt;
&lt;li&gt;Wirkungsgradbestimmung durch Trackingpixel und Kampangen&lt;/li&gt;
&lt;li&gt;Live Versandstatus und Fortschritt&lt;/li&gt;
&lt;li&gt;Tagging f&amp;uuml;r einen Versand&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Als Technologien kamen &lt;a href="http://neo4j.org"&gt;Neo4J&lt;/a&gt;, eine GraphDB, &lt;a href="http://www.rabbitmq.com/"&gt;RabbitMQ&lt;/a&gt;, eine MessageQueue und &lt;a href="https://vaadin.com/home"&gt;Vaadin&lt;/a&gt;, ein auf &lt;a href="http://code.google.com/webtoolkit/%20"&gt;GWT&lt;/a&gt; basierendes UI Framework zum Einsatz. Ich werde alle Technologien, deren Verwendung und eine kurze Begr&amp;uuml;ndung zur Wahl im Folgenden anrei&amp;szlig;en.&lt;/p&gt;
&lt;div&gt;&lt;strong&gt;RabbitMQ &lt;/strong&gt;ist ein MessageQueue Server, der von VMWare's SpringSource Devision in Erlang entwickelt wird. Die Wahl fiel auf RabbitMQ, weil er sowohl AMQP und JSONRPC over AMQP, als auch STOMP unterst&amp;uuml;tz und damit f&amp;uuml;r alle bei trivago eingesetzten Sprachen erreichbar ist. RabbitMQ ist zudem hochperformant und kommt unserem Vorhaben, Tonnen von Mail zu versenden, zu Gute.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;&lt;strong&gt;Neo4J&lt;/strong&gt;&amp;nbsp;ist eine &lt;a href="http://de.wikipedia.org/wiki/Graphdatenbank" target="_blank"&gt;Graphdatenbank&lt;/a&gt;, geschrieben in Java. Neo4J unterst&amp;uuml;tzt sowohl gerichtete, als auch gewichtete Kanten, ebenso wie Eigenschaften an Knoten. Das Konstrukt wird erg&amp;auml;nzt durch einen Lucene Index f&amp;uuml;r Knoten, &amp;uuml;ber den man recht schnelle Key-basierte Lookups durchf&amp;uuml;hren kann. Die Wahl fiel deswegen auf eine GraphDB, weil sie am sinnvollsten unsere Daten abbildet. Es entstehen sehr viele Beziehungen zwischen den Entit&amp;auml;ten unserer Applikation, die durch RDBMS - JOIN - Konstrukte sicherlich nur unter hohem Rechenaufwand abbildbar w&amp;auml;ren.Ein Beispiel ist die Relationsmenge zwischen Empf&amp;auml;nger (E), Empf&amp;auml;ngergruppe (G) und versendetem Newsletter (N). Hier gibt es folgende Relationen abzubilden:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;N -&amp;gt; versendet an -&amp;gt; G&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;E -&amp;gt; hat empfangen -&amp;gt; N&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;E -&amp;gt; hat geöffnet -&amp;gt; N&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;G -&amp;gt; enthält Empfänger -&amp;gt; E&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;Nehmen wir noch einen weiteren Knotentype "Bounce" (B) hinzu, wird das Konstrukt noch etwas interessanter:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;N &amp;lt;- ist hard-bounced &amp;lt;- B -&amp;gt; ist hard-bounced -&amp;gt; E&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;N &amp;lt;- ist soft-bounced &amp;lt;- B -&amp;gt; ist soft-bounced -&amp;gt; E&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;Damit l&amp;auml;sst sich also recht schnell darstellen, welcher Bounce-Typ bei welchem &amp;nbsp;Newsletter oder Empf&amp;auml;nger vorkam. Kanten lassen sich &amp;uuml;brigen mit linearem Aufwand z&amp;auml;hlen, wenn man den Knoten kennt!&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;&lt;strong&gt;Vaadin&lt;/strong&gt;&amp;nbsp;ist ein auf dem Google Web Toolkit basierendes UI Framework. Ich bin kein gro&amp;szlig;er HTML/CSS K&amp;uuml;nstler, also musste etwas anderes her, was erwachsen und optisch ansprechend war. Mit Vaadin konnte ich im Liferay - Bereich schon mal Erfahrungen sammeln und fand es schon damals sehr ansprechend. Wer mal Swing oder AWT benutzt hat, der wird sich bei Vaadin recht schnell heimisch f&amp;uuml;hlen. Jedenfalls bekommt man bei Vaadin jede Menge "geschenkt", was Optik, Kompatibilit&amp;auml;t und Technologie angeht. Ich kann euch nur den &lt;a href="http://demo.vaadin.com/sampler"&gt;Sampler&lt;/a&gt; ans Herz legen, dann versteht ihr was ich meine ;)&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;&lt;strong&gt;Personalisierung&lt;/strong&gt;&amp;nbsp; haben wir durch das Einbetten von &lt;a href="http://velocity.apache.org/engine/releases/velocity-1.7/"&gt;Apache's Velocity&lt;/a&gt;&amp;nbsp;erreicht. Die Mail Templates, aus denen man neue Newsletter erstellen kann, k&amp;ouml;nnen in Velocity geschrieben werden. Beim Versand wird der Template-Context mit den Daten des Empf&amp;auml;ngers, der Gruppe, der Kampange und Metadaten bef&amp;uuml;llt und f&amp;uuml;r jeden Empf&amp;auml;nger evaluiert. So wird eine komplette Personalisierung erm&amp;ouml;glicht.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;&lt;strong&gt;Tracking&lt;/strong&gt;&amp;nbsp;wird durch das automatische Einf&amp;uuml;gen eines &amp;lt;img/&amp;gt; Tags in die HTML Version der Mail erledigt. Das Image ruft ein separates Servlet auf, welches den Newsletter und die Empf&amp;auml;nger ID ben&amp;ouml;tigt. In der Folge kann dann die gerichtete Kante E -&amp;gt; hat ge&amp;ouml;ffnet -&amp;gt; N erstellt werden.&lt;/div&gt;
&lt;p /&gt;
&lt;div&gt;&lt;strong&gt;Tagging &lt;/strong&gt;erscheint vielleicht auf den ersten Blick f&amp;uuml;r einen Newsletter ein wenig sinnfrei. Wenn man jedoch die GraphDB in die Rechnung mit einbezieht und das Tracking hinzu nimmt, dann entsteht die M&amp;ouml;glichkeit "User-Interest-Tracking". Die Kobination Tag (T) sieht dann z. B. folgenderma&amp;szlig;en aus (Die Pipe soll zwei Kanten darstellen):&lt;/div&gt;
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;T &amp;lt;- hat Tag &amp;lt;- N &amp;lt;- hat empfangen | hat geöffnet &amp;lt;- E.&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

Aus diesen Relationen k&amp;ouml;nnen wir also, bei entsprechender Skalierung, ablesen, f&amp;uuml;r welche Tags sich ein Empf&amp;auml;nger interessiert.&lt;/div&gt;
&lt;/div&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/ein-newsletter-tool-selbst-gebaut-neo4j-rabbi"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/ein-newsletter-tool-selbst-gebaut-neo4j-rabbi#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/u9wKnNo-83U" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
      <media:content type="image/png" height="40" width="162" url="http://getfile2.posterous.com/getfile/files.posterous.com/import-yfpb/EomkuyqtFdEipaDfvsvbyGFbbBcFwmjJcfmIvbdpJGxvGyGoaECrIDkysJvk/media_httpxenjicomwpc_jgkAu.png">
        <media:thumbnail height="40" width="162" url="http://getfile7.posterous.com/getfile/files.posterous.com/import-yfpb/EomkuyqtFdEipaDfvsvbyGFbbBcFwmjJcfmIvbdpJGxvGyGoaECrIDkysJvk/media_httpxenjicomwpc_jgkAu.png.scaled500.png" />
      </media:content>
      <media:content type="image/jpeg" height="58" width="254" url="http://getfile6.posterous.com/getfile/files.posterous.com/import-yfpb/bHCbImgakuaJaxiBEsCqptlpdrgkroiGdgryfBtngAEgJtwmtIolAfrkhkvg/media_httpxenjicomwpc_xnEga.jpg">
        <media:thumbnail height="58" width="254" url="http://getfile8.posterous.com/getfile/files.posterous.com/import-yfpb/bHCbImgakuaJaxiBEsCqptlpdrgkroiGdgryfBtngAEgJtwmtIolAfrkhkvg/media_httpxenjicomwpc_xnEga.jpg.scaled500.jpg" />
      </media:content>
      <media:content type="image/png" height="50" width="211" url="http://getfile1.posterous.com/getfile/files.posterous.com/import-yfpb/aajnbJJsygxCtaGEBhowfIgnptvbzHzdlhHzFcDyphsAGrfDtsAzIxzxhBzz/media_httpxenjicomwpc_iecaF.png">
        <media:thumbnail height="50" width="211" url="http://getfile9.posterous.com/getfile/files.posterous.com/import-yfpb/aajnbJJsygxCtaGEBhowfIgnptvbzHzdlhHzFcDyphsAGrfDtsAzIxzxhBzz/media_httpxenjicomwpc_iecaF.png.scaled500.png" />
      </media:content>
    <feedburner:origLink>http://xenji.com/ein-newsletter-tool-selbst-gebaut-neo4j-rabbi</feedburner:origLink></item>
    <item>
      <pubDate>Tue, 01 Nov 2011 15:44:00 -0700</pubDate>
      <title>Mit ownCloud iCloud nachbauen</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/Dc--gfa1LPM/mit-owncloud-icloud-nachbauen</link>
      <guid isPermaLink="false">http://xenji.com/mit-owncloud-icloud-nachbauen</guid>
      <description>&lt;p&gt;
	&lt;p&gt;&lt;a href="http://xenji.com/wp-content/uploads/2011/11/owncloud-logo.png"&gt;&lt;/a&gt;&amp;nbsp;iCloud ist ja seit dem Erscheinen von iOS5 aus dem Beta - Stadium raus und wird ersetzt den bisherigen Me.com, bzw. den ganz alten .Mac Service. Ich bin recht froh, dass ich meine Me.com E-Mail nun kostenlos als Spamf&amp;auml;nger weiter betreiben kann. Die 79&amp;euro; im Jahr taten nach einiger Zeit ganz sch&amp;ouml;n weh. Wer nun kein iPhone besitzt oder einfach nur kein Interesse hat iCloud zu nutzen, dem sei ownCloud ans Herz gelegt. OwnCloud basiert auf bekannten und bew&amp;auml;hrten Technologien, darunter PHP 5.2, MySQL (alternativ auch SQLite oder PostgreSQL) und dem WebDAV Protokoll. Hinzu kommen noch CardDav und CalDav.  OwnCloud bringt, neben Kalender- und Kontaktsynchronisierung, auch Bookmarks und Datei-Storage mit. Hier wird noch zwischen Musikdaten, welche direkt a la GoogleMusic gestream'ed werden k&amp;ouml;nnen, und anderen Daten unterschieden. Die "anderen Daten" k&amp;ouml;nnen publiziert werden, &amp;auml;hnlich, wie man es vielleicht von Ubuntu One kennt.  Die Installation gestaltet sich recht einfach, die Nutzung ebenfalls. Die UI wird durch jQuery unterst&amp;uuml;tz und der Doctype steht auf HTML5 - wobei ich jedoch keine in HTML hinzugekommenen Elemente bisher gesehen habe.  Wer sich ownCloud anschauen will, der findet unter &lt;a href="http://owncloud.org"&gt;http://owncloud.org&lt;/a&gt; weitere Informationen. Es w&amp;auml;re jedoch ratsam, die Installation nicht auf einem unterdimensionierten Webspace zu versuchen. Wenn man eine mittlere Musiksammlung (als "mittel" nehm ich jetzt mal einfach 20 Gbyte) hochladen m&amp;ouml;chte, dann kann es beim Hostingangebot "WebVisitenkarte XYZ" doch recht schnell problematisch werden ;).&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/mit-owncloud-icloud-nachbauen"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/mit-owncloud-icloud-nachbauen#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/Dc--gfa1LPM" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
      <media:content type="image/png" height="64" width="280" url="http://getfile5.posterous.com/getfile/files.posterous.com/import-yfpb/fJcnAJtwJpgfxfEjueggudgqvtmGCIFtuvGGFkAGqDljindCkGqqbrgpygfp/media_httpxenjicomwpc_rpybv.png">
        <media:thumbnail height="64" width="280" url="http://getfile8.posterous.com/getfile/files.posterous.com/import-yfpb/fJcnAJtwJpgfxfEjueggudgqvtmGCIFtuvGGFkAGqDljindCkGqqbrgpygfp/media_httpxenjicomwpc_rpybv.png.scaled500.png" />
      </media:content>
    <feedburner:origLink>http://xenji.com/mit-owncloud-icloud-nachbauen</feedburner:origLink></item>
    <item>
      <pubDate>Tue, 18 Oct 2011 16:25:14 -0700</pubDate>
      <title>Weg von Squarespace - zurück zu Wordpress</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/SpMCsXjcf3A/weg-von-squarespace-zuruck-zu-wordpress</link>
      <guid isPermaLink="false">http://xenji.com/weg-von-squarespace-zuruck-zu-wordpress</guid>
      <description>&lt;p&gt;
	ePress ist ja leider noch in der Planung, sonst h&amp;auml;tte ich mir gern diesen Schritt gespart. Jedoch ist Squarespace einfach zu teuer geworden, gemessen an der erbrachten Leistung. Wordpress ist zwar auch nicht der Himmel auf Erden und ich hoffe, dass mir die Wahl nicht zum Verh&amp;auml;ngnis wird.

Ich m&amp;ouml;chte noch mal dazu aufrufen Feature Requests f&amp;uuml;r &lt;a href="https://github.com/ePress/ePressBlog" target="_blank"&gt;ePress&lt;/a&gt; zu erstellen. Macht einfach ein &lt;a href="https://github.com/ePress/ePressBlog/issues?sort=created&amp;amp;labels=RFC&amp;amp;direction=desc&amp;amp;state=open" target="_blank"&gt;neues Ticket auf GitHub&lt;/a&gt; auf und wir schauen es uns an!
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/weg-von-squarespace-zuruck-zu-wordpress"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/weg-von-squarespace-zuruck-zu-wordpress#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/SpMCsXjcf3A" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/weg-von-squarespace-zuruck-zu-wordpress</feedburner:origLink></item>
    <item>
      <pubDate>Mon, 17 Oct 2011 21:19:14 -0700</pubDate>
      <title>PageRank für Community Ratings nutzen - Teil 2</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/oINdNik0e-Y/pagerank-fur-community-ratings-nutzen-teil-2</link>
      <guid isPermaLink="false">http://xenji.com/pagerank-fur-community-ratings-nutzen-teil-2</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Im zweiten Teil der Serie nehmen wir uns mal das Datenmodell vor. &lt;br /&gt;Zuerst brauchen wir einen Nutzer, der durch einen Knoten im Graph dargestellt wird. Dieser Nutzer erh&amp;auml;lt die Eigenschaften "id", welche in den Lucene Index von Neo4J &amp;uuml;bertragen wird, und einen PageRank. Vom Nutzer selbst gehen bis zu zwei verschiedene Kantentypen ab. Die "RATE_SUBJECT" Kante und die "RATE_USER" Kante. Beide werden mit der Eigenschaft "value" versehen. Daraus schlie&amp;szlig;t sich schon die erste eingehende Kante, denn der User kann ebenfalls bewertet werden (in Form eines RATE_USER). Die RATE_USER Kante bekommt zus&amp;auml;tzlich noch eine Eigenschaft, die einen Bezug zur Bewerteten Bewertung darstellt. Diese ist f&amp;uuml;r unsere Berechnung nicht direkt relevant, l&amp;auml;sst sich aber f&amp;uuml;r Visualisierungszwecke gut nutzen. Die RATES_SUBJECT Kante bekommt die subject id aus dem selben Grund verpasst. Man k&amp;ouml;nnte das Subject noch als Cluster Kriterium f&amp;uuml;r den PageRank einsetzen, was aber die Komplexit&amp;auml;t deutlich steigern w&amp;uuml;rde. Hinzu kommt ein Knoten f&amp;uuml;r das zu bewertende Subject. Dieser bekommt auch die Eigenschaft "id" und einen aus dem Grahen errechneten Faktor, der in das Ranking der Suche einflie&amp;szlig;t. Aktuell evaluiere ich die Menge der Nodes, die bei einem Vollimport aller Ratings seit 2008 entstehen w&amp;uuml;rden. 500.000 and counting. Es bleibt zu evaluieren, ob Neo4J sich bei diesen Mengen noch als praktikabel erweist...&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/pagerank-fur-community-ratings-nutzen-teil-2"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/pagerank-fur-community-ratings-nutzen-teil-2#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/oINdNik0e-Y" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/pagerank-fur-community-ratings-nutzen-teil-2</feedburner:origLink></item>
    <item>
      <pubDate>Wed, 12 Oct 2011 19:01:38 -0700</pubDate>
      <title>PageRank für Community Ratings nutzen - Teil 1</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/bAkd-Znmn10/pagerank-fur-community-ratings-nutzen-teil-1</link>
      <guid isPermaLink="false">http://xenji.com/pagerank-fur-community-ratings-nutzen-teil-1</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Heute starte ich eine Serie &amp;uuml;ber ein Thema mit dem ich mich aktuell besch&amp;auml;ftige. Dabei geht es unter Anderem um die Qualit&amp;auml;t von Suchergebnissen und die Einbindung von Crowd Sourcing zur Verbesserung der Suchergebnisse unter Verwendung von Graph-Datenbanken - in diesem Fall evaluiere ich Neo4J - und dem PageRank Algoritmus.&lt;/p&gt;
&lt;p&gt;In vereinfachter Form l&amp;auml;uft das so ab:&lt;/p&gt;
&lt;p&gt;Nutzer bewerten ein Subjekt (z. B. ein Toaster bei Amazon) und geben ein nummerisches Rating innerhalb einer definierten Skala ab (0 - X Sterne, Punkte, etc). Diese Information flie&amp;szlig;t in das Suchergebnis ein und verbessert die Relevanz des Toasters. Gehen wir jedoch davon aus, dass der Nutzer, der als einziger bisher den Toaster bewertet hat, &amp;uuml;berhaupt keine Ahnung vom Ger&amp;auml;t hat und den gr&amp;ouml;&amp;szlig;ten Mist in seiner Bewertung verfasst hat - dennoch aber die volle Punktzahl vergeben hat. Fazit daraus: Die Bewertung ist unbrauchbar. Um diesem Umstand Sorge zu tragen hat man in der Vergangenheit das Konzept &amp;ldquo;Bewerte die Bewertung&amp;rdquo; eingef&amp;uuml;hrt. Damit sind wir in der Position, qualitativ minderwertige Bewertungen zu filtern. Spinnen wir den Faden wiederum etwas weiter, dann merken wir, dass hier der selbe Strick auftaucht, den wir auch bei der initialen Bewertung hatten. Wer sagt uns, dass der Nutzer, der die Bewertung bewertet hat, ebenfalls Ahnung davon hat?&lt;/p&gt;
&lt;p&gt;Diese Fragestellung endet in einer Endlosschleife ;)&lt;/p&gt;
&lt;p&gt;Um dem Problem auf die Schliche zu kommen schaut man sich den &lt;a href="http://de.wikipedia.org/wiki/PageRank"&gt;PageRank Algoritmus&lt;/a&gt; an und transportiert ihn vom Thema Webseiten und Hyperlinks auf Nutzer und Bewertungen. Hinzu kommt jedoch die Gewichtung der gerichteten Kanten (X Sterne, Punkte, etc.). Um diesen Punkt ad&amp;auml;quat abzubilden bedient man sich einer Graph-Datenbank, welches das &lt;a href="https://github.com/tinkerpop/blueprints/wiki/Property-Graph-Model"&gt;Property-Graph Modell&lt;/a&gt; unterst&amp;uuml;tzt. Damit l&amp;auml;sst sich die Speicherung der Daten, die wir f&amp;uuml;r die PageRank basierte Auswertung ben&amp;ouml;tigen, realisierten.&lt;/p&gt;
&lt;p&gt;Ich schraub jetzt erst mal ein wenig ;)&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/pagerank-fur-community-ratings-nutzen-teil-1"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/pagerank-fur-community-ratings-nutzen-teil-1#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/bAkd-Znmn10" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/pagerank-fur-community-ratings-nutzen-teil-1</feedburner:origLink></item>
    <item>
      <pubDate>Tue, 13 Sep 2011 20:16:49 -0700</pubDate>
      <title>Enterprise Wordpress - es geht los.</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/aNMDpwUSzTg/enterprise-wordpress-es-geht-los</link>
      <guid isPermaLink="false">http://xenji.com/enterprise-wordpress-es-geht-los</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Ich erwarte euch auf GitHub, die ihr so flei&amp;szlig;ig eure Hilfe angeboten habt ;)&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ePress/blog"&gt;https://github.com/ePress/blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Es bleibt dabei, schickt mir eine Nachricht auf GitHub (xenji) oder einfach per Twitter (@xenji) Bescheid geben.&lt;/p&gt;
&lt;p&gt;Der Name ist Verhandlungssache und bleibt erstmal ein Arbeitstitel. Die passende Google Group findet sich hier: &lt;a href="http://groups.google.com/group/epressblog"&gt;http://groups.google.com/group/epressblog&lt;/a&gt;&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/enterprise-wordpress-es-geht-los"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/enterprise-wordpress-es-geht-los#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/aNMDpwUSzTg" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/enterprise-wordpress-es-geht-los</feedburner:origLink></item>
    <item>
      <pubDate>Sun, 11 Sep 2011 13:16:36 -0700</pubDate>
      <title>Enterprise Wordpress - kann es losgehen?</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/oyRUljf3Ang/enterprise-wordpress-kann-es-losgehen</link>
      <guid isPermaLink="false">http://xenji.com/enterprise-wordpress-kann-es-losgehen</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Der Post widmet sich allen Kommentarautoren bei PHM und bei meinem letzten Artikel zum Thema Wordpress Enterprise. &lt;/p&gt;
&lt;p&gt;Da viele von euch die Bereitschaft gezeigt haben an einem solchen Projekt teilzunehmen, w&amp;uuml;rde ich das ganze gern auf den Weg bringen. Ich denke, dass GitHub eine allgemein akzeptierte Plattform w&amp;auml;re? Oder doch lieber Google Code (SVN, Git oder Hg)? &lt;/p&gt;
&lt;p&gt;Der erste Schritt w&amp;auml;re wohl im jeweiligen Wiki die Konzepte und Technologien festzuhalten und in der Folge die Umsetzungsaufgaben zu verteilen. Ist einer der Mitlesenden zuf&amp;auml;llig Projektmanager und w&amp;auml;re interessiert an einer Planungsunterst&amp;uuml;tzung?&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/enterprise-wordpress-kann-es-losgehen"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/enterprise-wordpress-kann-es-losgehen#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/oyRUljf3Ang" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/enterprise-wordpress-kann-es-losgehen</feedburner:origLink></item>
    <item>
      <pubDate>Thu, 08 Sep 2011 07:33:23 -0700</pubDate>
      <title>Enterprise Wordpress</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/siELODw1rZM/enterprise-wordpress</link>
      <guid isPermaLink="false">http://xenji.com/enterprise-wordpress</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Ich greife mal &lt;a href="http://www.phphatesme.com/blog/projektwerk/projektwerkstatt-wordpress-enterprise/"&gt;Nils&amp;rsquo; Idee eines &amp;ldquo;Enterprise Wordpress&amp;rdquo;&lt;/a&gt; hier auf und spinne ein wenig herum.&lt;/p&gt;
&lt;p&gt;In den Kommentaren wurde diskutiert, ob man nicht Symfony2 oder auch generell ein Framework einsetzen solle oder welche Datenbankart es sein soll. Ich schreib meine Vorschl&amp;auml;ge dazu mit entsprechender Begr&amp;uuml;ndung mal runter ;)&lt;/p&gt;
&lt;h3&gt;Datenbank: MongoDB&lt;/h3&gt;
&lt;p&gt;Die Anatomie eines Blogposts kommt einem Dokument sehr nahe, daher sehe ich eine dokumentenorientierte Datenbank ganz weit vorn. &lt;a href="http://www.mongodb.org/"&gt;MongoDB&lt;/a&gt; ist deswegen meine Wahl, weil es im Punkt der Abfrage von Daten einfacher zu verstehen ist, als eine &lt;a href="http://couchdb.apache.org/"&gt;CouchDB&lt;/a&gt;. Index Queries sind halt greifbarer f&amp;uuml;r einen MySQL Umsteiger als eine Map &amp;amp; Reduce Funktionalit&amp;auml;t. Wenn nur ich das so sehe, dann kann es auch gern eine CouchDB sein - w&amp;auml;re mir pers. sogar lieber. Es kam auch ein Kommentar, der nach Beidem verlangte. An dieser Stelle muss ich mich jedoch klar dagegen aussprechen. Die Art der Abfragen und der Ansatz der Perfomanceoptimierung sind grunds&amp;auml;tzlich anders - ein Wrapper w&amp;uuml;rde also den jeweiligen Besonderheiten kaum gerecht werden.&lt;/p&gt;
&lt;h3&gt;Backend: ExtJS (jetzt &lt;a href="http://www.sencha.com/"&gt;Sencha&lt;/a&gt;) und PHP&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.pimcore.org/"&gt;Pimcore&lt;/a&gt; hat es auf exzellente Art vorgemacht und ich finde dieses gute Beispiel immitationsw&amp;uuml;rdig. Gerade die M&amp;ouml;glichkeit, &amp;uuml;ber Widgets eigene Masken zu definieren, ist f&amp;uuml;r z. B. Plugin Entwickler wunderbar einfach. Wer jetzt nicht weiss, wo von ich rede, der sollte sich mal Objekte im Pimcore Backend anschauen. Sencha bringt auch einen &lt;a href="http://www.sencha.com/products/touch/"&gt;Support f&amp;uuml;r Mobile Devices&lt;/a&gt; mit, daher kann man auch sehr sch&amp;ouml;n Apps f&amp;uuml;r Touch Devices bauen.&lt;/p&gt;
&lt;h3&gt;Frontend: Pure PHP 5.3 mit jQuery und selektivem jQueryUI&lt;/h3&gt;
&lt;p&gt;Nein, ich bin kein Framework-Muffel, sehe aber nicht die Notwendigkeit f&amp;uuml;r ein Blogsystem ein ganzes Framework Ramp-up &amp;ldquo;auszugeben&amp;rdquo;, wenn einer der Hauptaspekte des Rewrites Performance ist. Sehr wohl bin ich daf&amp;uuml;r Komponentenframeworks, wie z. B. Teile vom ZF(2), SF2 oder den ZetaComponents zu nutzen, wo es Sinn macht. jQuery ist f&amp;uuml;r mich immer noch das beste Framework im JavaScript bereich. jQueryUI ist allerdings ganz sch&amp;ouml;n Fett geworden und muss daher sehr selektiv eingesetzt werden.&lt;/p&gt;
&lt;h3&gt;Caching: Varnish inkl. ESI, Redis&lt;/h3&gt;
&lt;p&gt;Varnish ist aktuell das schnellste Pferd auf dem Platz und gerade per &lt;a href="http://www.phphatesme.com/blog/webentwicklung/edge-side-includes/"&gt;ESI&lt;/a&gt; macht die Sache Spa&amp;szlig;. &lt;a href="http://redis.io"&gt;Redis &lt;/a&gt;ist f&amp;uuml;r mich der &amp;ldquo;Memcached successor&amp;rdquo; und geh&amp;ouml;rt in jedes Setup was vorher mit Memcached gearbeitet hat.&lt;/p&gt;
&lt;h3&gt;&amp;ldquo;Sontiges&amp;rdquo;&lt;/h3&gt;
&lt;p&gt;Ansonsten gibt es ja bei Wordpress noch die Probleme, die immer und immer wieder kehren. Bei Lastverteilung fehlt die M&amp;ouml;glichkeit ein gemeinsames CDN zu definieren. Meist h&amp;auml;ngt man dann mit einer NFS-mount L&amp;ouml;sung herum. Diese geht bis zu einem gewissen Punkt auch gut, bei zu viel I/O geht es jedoch eher schlecht.&lt;/p&gt;
&lt;p&gt;Trennung von Frontend und Backen ist ein weiteres Thema. Es sollte einen &amp;ldquo;Shared Library&amp;rdquo; Ordner geben, der auf Beiden vorhanden sein muss, jedoch sollte man ein oder mehrere Frontend betreiben k&amp;ouml;nnen, ohne dass man auf jedem Frontend ein Backend &amp;ldquo;geschenkt bekommt&amp;rdquo;. Ein Backend geh&amp;ouml;rt aus meiner Sicht auf einen IP-Range beschr&amp;auml;nkten Server.&lt;/p&gt;
&lt;p&gt;Workflows - ein Feature, was ich sehr vermisse. Blogs sind Redaktionssysteme geworden. So erschreckend das sein mag und so sehr Systeme wie &lt;a href="http://www.e-spirit.com/"&gt;FirstSpirit &lt;/a&gt;an dieser Stelle besser sein k&amp;ouml;nnten, so intensiv werden Wordpress &amp;amp; Co. als eben solche gebraucht. Warum also nicht wenigstens einen vier-Augen-Workflow implementieren?&lt;/p&gt;
&lt;p&gt;Vielleicht kann man ja sogar auf das Release von PHP5.4 bauen und sich Traits mal genauer anschauen. Ich denke, dass gerade in der Pluginentwicklung Traits von Vorteil sein k&amp;ouml;nnten.&lt;/p&gt;
&lt;p&gt;Zu guter Letzt muss ich noch einen Kommentar von mir am original Artikel korrigieren. Ich w&amp;uuml;rde das WP-EE nicht Plugin-kompatibel schreiben. Der mitgeschleppte M&amp;uuml;llberg w&amp;auml;re zu enorm ;). Sicherlich bin ich nicht auf alle Themen, die man an WP optimieren k&amp;ouml;nnte, eingegangen. Da liegt es nun am eifrigen Leser den n&amp;auml;chsten Blogpost oder Kommentar zu schreiben und die Idee weiter zu spinnen. Lasst mal was h&amp;ouml;ren!&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/enterprise-wordpress"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/enterprise-wordpress#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/siELODw1rZM" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/enterprise-wordpress</feedburner:origLink></item>
    <item>
      <pubDate>Sun, 04 Sep 2011 22:09:29 -0700</pubDate>
      <title>Einer für alle - Import unification</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/MHIOyuNATOQ/einer-fur-alle-import-unification</link>
      <guid isPermaLink="false">http://xenji.com/einer-fur-alle-import-unification</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Mashups sind nichts Neues mehr. Die halbe digitale Welt besteht aus der Aggregation von Inhalten aus verschiedensten Quellen. Dieser Artikel beschreibt eine Herangehensweise aus technischer Sicht, um solche Importe aus performante und skalierbare Weise zu planen und zu entwickeln.&lt;/p&gt;&lt;p&gt;Die Ausgangssituation ist folgenderma&amp;szlig;en definiert:&lt;br /&gt;Gegeben ist eine Plattform in beliebiger Hochsprache mit der M&amp;ouml;glichkeit XML Daten performant zu verarbeiten. Diese Plattform stellt Daten in aufbereiteter Form Nutzern zur Verf&amp;uuml;gung und bezieht diese Daten aus einer oder mehreren Quellen in diversen strukturierten Formaten (XML, JSON, CSV, etc.). Alle Datens&amp;auml;tze werden in einer beliebigen, relationalen Datenbank persistiert. NoSQL Datenbanken werden hier bewusst ausgelassen, da die M&amp;ouml;glichkeiten, die diese Art der Datenhaltung mitbringen, das Ziel dieses Artikels &amp;uuml;berschreiten w&amp;uuml;rden und eher in einem weiteren Artikel Beachtung finden sollten.&lt;/p&gt;&lt;p&gt;Ein erster Gedankengang geht in die Richtung f&amp;uuml;r jede der gegebenen Quellen einen eigenen Prozess zu planen, ein Mapping oder eine Transformation zu definieren und darauf hin einen Importer zu entwickeln, der diesem Prozess Folge leistet. Diese Herangehensweise hat Vor- und Nachteile. Der, in meinen Augen, gr&amp;ouml;&amp;szlig;te Vorteil liegt in der Detailtreue des einzelnen Imports. Er kann auf die Eigenheiten und Feinheiten der jeweiligen Datenstrukturen eingehen. Doch hier beginnt schon der erste nachteilige Aspekt zu wirken, denn es schleicht sich meist zu viel Applikationslogik mit in den Import ein, der im Grunde nur Daten transportieren und transformieren soll. Skalieren wir das Szenario nun auf 100 verschiedene Importe, so wird eine Anpassung an der eigenen Datenhaltung zum teuren Unterfangen. Jeder Import muss daraufhin angepasst werden, getestet werden und vielleicht sogar neu optimiert werden. In meinen Augen ein erschreckendes Bild, dass es, nicht nur aus betriebswirtschaftlicher Sicht, zu vermeiden gilt. Ein weiterer Nachteil ist, dass solche Importe meist selbst schlecht skalieren. Wenn ein Import Prozess bei einer Eingangsdatenmenge von 100 MB 60 Sekunden zur Verarbeitung ben&amp;ouml;tigt, dann werden 1000 MB im besten Fall 600 Sekunden brauchen. Schneller kann es nur unter zwei Bedingungen gehen - ich kaufe bessere Hardware oder ich optimiere den Import. Beides hat seine Grenzen, denn irgendwann habe ich den schnellsten Server und den schnellsten (und zumeist auch am wenigsten wartbaren) Quellcode - das Ende der Fahnenstange in diesem Fall.&lt;/p&gt;&lt;p&gt;Es ist hoffentlich deutlich geworden, dass eine Alternative gefunden werden muss, die neben der Wartbarkeit und Skalierbarkeit auch Geschwindigkeit hergeben muss. &lt;/p&gt;&lt;p&gt;F&amp;uuml;r diese L&amp;ouml;sung ist ein wenig umdenken erforderlich. Wir teilen daf&amp;uuml;r die Aufgabe in zwei Teile. Der Erste ist adaptiv, also auf das Eingangsformat abgestimmt. Der Zweite ist stetig der Selbe, also ein einziges, fest definiertes und validierbares Format, in diesem Szenario XML, zu importieren. Es dr&amp;auml;ngt sich die Frage auf, was sich damit an der L&amp;ouml;sung der Problemstellung &amp;auml;ndert? Einiges, wenn nicht sogar alles.&lt;/p&gt;&lt;p&gt;Wir rollen das Feld von hinten auf und beginnen mit dem zweiten Teil, der Import Phase. Wir gewinnen durch die Festlegung eines einzigen Formates die M&amp;ouml;glichkeit den Import auf genau ein Format zu optimieren - sowohl den Speicherverbrauch, als auch die Ausf&amp;uuml;hrungsgeschwindigkeit. &amp;Auml;nderungen an der Datenstruktur brauchen nur in einem Import reflektiert werden. Der Aufwand f&amp;uuml;r eine &amp;Auml;nderung wird damit berechenbar. Obendrein bekommen wir mit einem Bruchteil von Tests eine deutlich h&amp;ouml;here Abdeckung zu Stande - was wiederum zu erh&amp;ouml;hter Qualit&amp;auml;t f&amp;uuml;hrt. Diese Kausalkette darf jeder gern f&amp;uuml;r sich selbst fortsetzen, die Richtung sollte jedoch klar geworden sein.&lt;/p&gt;&lt;p&gt;In der ersten Phase, der Unify Phase, geht es schlich darum, das Fremdformat in das Eigene zu &amp;uuml;berf&amp;uuml;hren. Auch dieser Prozess kann f&amp;uuml;r sich selbst pro Quelle optimiert werden. Der Vorteil, der hierbei jedoch heraus sticht, ist die gewonnene Verteilbarkeit dieses Prozesses. Unter Verwendung von z. B. Hadoop l&amp;auml;sst sich die Verarbeitungsgeschwindigkeit nicht nur mit der Leistung der Hardware sonder viel mehr mit der Anzahl der Hardware skalieren.&lt;/p&gt;&lt;p&gt;Sicherlich l&amp;auml;sst sich dieser Ansatz nicht auf jeden Import in jedes System &amp;uuml;bertragen, jedoch ist es gerade f&amp;uuml;r best&amp;auml;ndige Systeme (z.B. Shops, News Sites oder Aggregatorsuchen) aus meiner Sicht ein Gewinn.&lt;/p&gt;&lt;p&gt;An dieser Stelle noch ein Hinweis aus eigener Erfahrung. Die Import Phase ist vom Grunde her ebenfalls verteilbar. Jedoch ist hier die Leistung der Datenbank-Server, bzw. -Hardware der "Deckel". Man kann schon mit einem kleinen Hadoop Cluster einen gut dimensionierten Datenbank Server ausknocken. Es ist Vor- und Umsicht geboten ;).&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/einer-fur-alle-import-unification"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/einer-fur-alle-import-unification#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/MHIOyuNATOQ" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/einer-fur-alle-import-unification</feedburner:origLink></item>
    <item>
      <pubDate>Sun, 31 Jul 2011 19:39:52 -0700</pubDate>
      <title>Riot - Leichtgewicht unter den Java CMS</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/SqAskGtX2kQ/riot-leichtgewicht-unter-den-java-cms</link>
      <guid isPermaLink="false">http://xenji.com/riot-leichtgewicht-unter-den-java-cms</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Auf meiner stetigen Suche nach neuen CM Systemen bin ich vor einiger Zeit &amp;uuml;ber &lt;a href="http://www.riotfamily.org"&gt;Riot&lt;/a&gt; gestolpert. Riot erscheint mir als, wenn man das Wort im Java Bereich wirklich gebrauchen darf, als angenehm leicht und wenig &amp;uuml;berladen - wenn man &lt;a href="http://dotcms.com/"&gt;dotCMS&lt;/a&gt; oder &lt;a href="http://www.opencms.org/"&gt;openCMS&lt;/a&gt; dagegen betrachtet. Riot basiert auf &lt;a href="http://static.springsource.org/spring/docs/3.0.x/reference/mvc.html"&gt;Spring&amp;rsquo;s MVC&lt;/a&gt; und verwendet neben &lt;a href="http://www.hibernate.org/"&gt;Hibernate&lt;/a&gt; noch weitere OpenSource Bibliotheken, z. B. &lt;a href="http://freemarker.sourceforge.net/"&gt;Freemaker&lt;/a&gt;. Das Skeleton verf&amp;uuml;gt &amp;uuml;ber ein &lt;a href="http://ant.apache.org/"&gt;Ant&lt;/a&gt; Buildfile und das Dependency Management erfolgt &amp;uuml;ber &lt;a href="http://ant.apache.org/ivy/"&gt;Ivy&lt;/a&gt;. Die original Sourcen werden per &lt;a href="http://www.gradle.org/"&gt;Gradle&lt;/a&gt; gebaut.&lt;/p&gt;

&lt;p&gt;Riot ist ein seitenbasiertes CMS, es gibt als erstmal keine Trennung von Struktur und Content. Der Content wird direkt per Inline-Edit gepflegt. In den Templates werden Bereiche definiert, in denen Freemaker Macros und sog. &lt;a href="http://www.riotfamily.org/docs/components.html"&gt;Components&lt;/a&gt; - persistente, komplexe Datentypen - ein oder mehrfach platziert werden d&amp;uuml;rfen. &lt;/p&gt;

&lt;p&gt;Die Components machen das System f&amp;uuml;r mich erst interessant, da man eigentlich jeden Anwendungsfall im unteren und mittleren Komplexit&amp;auml;tsbereich damit gut abdecken kann. &lt;/p&gt;

&lt;p&gt;Das Produkt selbst scheint eine open-source&amp;rsquo;ed Agenturl&amp;ouml;sung zu sein. Nach einigem Suchen kommt man von Riotfamily auf die nicht ganz unbekannte Agentur &lt;a href="http://www.neteye.de/"&gt;NETEYE&lt;/a&gt; aus Hamburg. Die &lt;a href="https://github.com/riotfamily/riot"&gt;Sourcen&lt;/a&gt; wurden freundlicherweise auf Github zur Verf&amp;uuml;gung gestellt.&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/riot-leichtgewicht-unter-den-java-cms"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/riot-leichtgewicht-unter-den-java-cms#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/SqAskGtX2kQ" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/riot-leichtgewicht-unter-den-java-cms</feedburner:origLink></item>
    <item>
      <pubDate>Tue, 12 Jul 2011 06:46:57 -0700</pubDate>
      <title>XML, Text, Hadoop, CouchDB und die Google Search Engine</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/QCaWWMwnh54/xml-text-hadoop-couchdb-und-die-google-search</link>
      <guid isPermaLink="false">http://xenji.com/xml-text-hadoop-couchdb-und-die-google-search</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Gr&amp;ouml;&amp;szlig;ere Datenmengen bringen deutlich andere Herausforderungen mit sich. Durch eine Teststellung ergab sich eine Herausforderung, deren L&amp;ouml;sung eine kleine Evolution durchgemacht hat. Ziel des Vorhabens ist, jedes Element aus der ersten Menge mit einer unbekannten Anzahl von weiteren Informationen aus der zweiten Menge anzureichern und das Ergebnis zu einer f&amp;uuml;r die Google Search Appliance brauchbaren HTML Seite zu vereinen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ausgangssituation&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;18 Gbyte XML Daten in einzelnen Dateien&lt;/li&gt;
&lt;li&gt;ca. 60 Gbyte &amp;ldquo;Metadaten&amp;rdquo; in einzelnen Dateien (JPG, HTM, XML) und einer 1:n Zuordnung zu den XML Daten aus dem ersten Punkt&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; In den XML Daten, nennen wir sie mal &amp;ldquo;Produkte&amp;rdquo;, gibt es zu jedem Produkt verschiedene Typen von Metadaten. Dies k&amp;ouml;nnen Bilder, erweiterte Beschreibungen und sonstige Zusatzinformationen sein. Jedes Produkt hat mindestens eine eindeutige ID aus einem von zwei Nummernkreisen. Diese ID findet sich ebenfalls im Dateinamen der zugeh&amp;ouml;rigen Metadaten wieder. Die Anzahl der Produkte liegt bei ca. 5,7 Mio.&lt;/p&gt;
&lt;p&gt;Beispiel: Produkt 4711 -&amp;gt; Produktbilder/Bild_4711_Ansicht1.jpg&lt;/p&gt;
&lt;p&gt;Der erste Ansatz ist es, bei einer Iteration durch alle Produkte, jeweils alle Metadaten zu finden. Hier kann ein kleiner Shell Aufruf schon ausreichen:&lt;/p&gt;
&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;find . -name &amp;quot;*_4711_*&amp;quot; -type f&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Dabei sollte 4711 nat&amp;uuml;rlich durch den aktuellen Wert des Produktes ersetzt werden. Wer nun die H&amp;auml;nde &amp;uuml;ber dem Kopf zusammenschl&amp;auml;gt und I/O Probleme wittert, dem sei gesagt &amp;hellip; yes! Ist verflucht lahm.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Kurz ein paar Variabeln definiert&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;p = Produkt&lt;/p&gt;
&lt;p&gt;C&lt;span style="vertical-align: sub;"&gt;(p)&lt;/span&gt; = Count&lt;span style="vertical-align: sub;"&gt;(Produkt)&lt;/span&gt; -&amp;gt; ca. 5.700.000&lt;/p&gt;
&lt;p&gt;m = eine Metainformation&lt;/p&gt;
&lt;p&gt;C&lt;span style="vertical-align: sub;"&gt;(m)&lt;/span&gt; = Count&lt;span style="vertical-align: sub;"&gt;(m)&lt;/span&gt; Gesamtanzahl der Metadaten -&amp;gt; ca. 25.000.000&lt;/p&gt;
&lt;p&gt;k = Konstante f&amp;uuml;r die Kosten des I/O Seek auf der HDD, hier in Sekunden gemessen.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Laufzeiten&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Bei einer Laufzeit von O(C&lt;span style="vertical-align: sub;"&gt;(p)&lt;/span&gt; * C&lt;span style="vertical-align: sub;"&gt;(m)&lt;/span&gt;) ist die Platte (Seek I/O) hier sicherlich noch als Konstante zu sehen, womit sich O(C&lt;span style="vertical-align: sub;"&gt;(p)&lt;/span&gt; * C&lt;span style="vertical-align: sub;"&gt;(m)&lt;/span&gt; * k) ergibt und nach erster Beobachtung k &amp;gt; 8 ist. Ohne es bewiesen zu haben, liegt die errechnete Laufzeit bei weit mehr als einem Jahr ;).&lt;/p&gt;
&lt;p&gt;Die n&amp;auml;chste Variante war per find ein Directory Index zu erstellen, also find &amp;uuml;ber alle Verzeichnisse zu schicken und das Ergebnis in Textdateien zu Speichern. Diese Textdateien kann man mit grep durchsuchen. Auch hier entsteht eine Laufzeit von O(C&lt;span style="vertical-align: sub;"&gt;(p)&lt;/span&gt; * C&lt;span style="vertical-align: sub;"&gt;(m)&lt;/span&gt; * k), wobei sich k = 8 herausstellte. Auch hier liegt die Laufzeit bei ca. einem Jahr.&lt;/p&gt;
&lt;p&gt;Die Anzahl der Metadaten pro Produkt spielt keine Rolle, da immer die gesamte Menge an Metadaten durchsucht werden muss.&lt;/p&gt;
&lt;p&gt;Das Problem bei beiden Ans&amp;auml;tzen besteht deutlich in der Multiplikation der Ergebnismengen. 142.500.000 Operationen sind auch ohne Konstante schon eine viel zu gro&amp;szlig;e Menge. &lt;/p&gt;
&lt;p&gt;Was kann man also tun, damit man die Multiplikation los wird? Es m&amp;uuml;sste eine M&amp;ouml;glichkeit geschaffen werden, dass der Iterator nur eine &amp;ldquo;Anfrage&amp;rdquo; an die Ergbnismenge stellen muss und daraufhin alle Metadaten zur&amp;uuml;ck geliefert werden - alternativ ist die Menge 0 auch eine valide Antwort. Um dies zu erreichen brauchen wir einen Index, der auf Basis eines Schl&amp;uuml;ssels eine Liste von Werten zur&amp;uuml;ck geben kann. Dieser Index muss einmalig bef&amp;uuml;llt werden. Die technologische Entscheidung fiel hier auf Hadoop f&amp;uuml;r die Vorbereitung der Daten, ein PHP Script zum Einf&amp;uuml;gen der Daten in den Index und eine CouchDB als  eigentlicher Index. Vorteil bei dieser Konstellation ist, dass CouchDB &amp;uuml;ber HTTP angesprochen werden kann. Es gibt also nur zwei M&amp;ouml;glichkeiten f&amp;uuml;r die Antwort auf die Frage nach dem Schl&amp;uuml;ssel: HTTP 200 OK oder HTTP 404 NOT FOUND. Sicherlich k&amp;ouml;nnte man dies auch &amp;uuml;ber Redis abbilden, jedoch war die Anbindung der CouchDB einfacher und schneller f&amp;uuml;r diesen Anwendungfall.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wir f&amp;uuml;hren neue Variabeln ein&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;h = Vorbereitungszeit Hadoop Map &amp;amp; Reduce&lt;/p&gt;
&lt;p&gt;v = Vorbereitungszeit f&amp;uuml;r den Index&lt;/p&gt;
&lt;p&gt;r = Konstante f&amp;uuml;r die Kosten eines HTTP Requests, ebenfalls in Sekunden gemessen.&lt;/p&gt;
&lt;p&gt;Wenn wir unsere Rechnung unter den neuen Gesichtspunkten aufsetzen, ergibt sich O(h + v + C&lt;span&gt;(p)&lt;/span&gt; * r). Durch die Nutzung der Loopback Device konnten wir r = 0.2 erreichen. Die Konstanten h und v sind im Vergleich zur voherigen Multiplikation nahezu l&amp;auml;cherlich klein. h liegt bei 146 Sekunden und v bei ca. 600 Sekunden.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hadoop als Vorbereiter&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Die im &lt;em&gt;find &lt;/em&gt;vorbereiteten Daten werden nun zu 60Mbyte Bl&amp;ouml;cken zusammengefasst. Hierbei hilft uns ein kleines PHP Script. Man kann hier auch die von Hadoop angebotene Klasse CombineFileInputFormat verwenden.  Die neu geschaffenen Dateien kommen dann auf das HDFS und sind damit f&amp;uuml;r den Map &amp;amp; Reduce Schritt verf&amp;uuml;gbar.&lt;/p&gt;
&lt;p&gt;Der Map Job ist recht simpel. Das Ergebnis des finds wird zeilenweise an die Map Methode geliefert. Der LongWritable key ist der byte-Offset, der Text value ist die Zeile selbst.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;public void map(LongWritable key, Text value, OutputCollector output, Reporter reporter) throws IOException {
        final String line = value.toString();
        final String[] parts = line.split(&amp;quot;/&amp;quot;);
                
        if (parts.length &amp;gt; 1) {
                final String filename = parts[parts.length-1];
                final String[] fileParts = filename.split(&amp;quot;_&amp;quot;);
                
                final StringBuilder sb = new StringBuilder();
                sb.append(fileParts[1]);
                sb.append(fileParts[0]);
                
                keyVal.set(sb.toString());
                valVal.set(line);
                
                output.collect(keyVal, valVal);
        }
        else {
                reporter.incrCounter(&amp;quot;org.apache.hadoop.mapred.Task$Counter&amp;quot;, &amp;quot;MAP_SKIPPED_RECORDS&amp;quot;, 1);
        }
}&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Wenn der Mapper alle Values, in unserem Fall also die Pfade, zu den Keys, also den IDs, gefunden hat, wird das Ergebnis an den Reducer weitergeleitet. Der Reducer iteriert &amp;uuml;ber alle Values zum Key und erstellt bereit einen String, der sp&amp;auml;ter als Liste in JSON weiterverwendet werden kann.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div class="CodeRay"&gt;
  &lt;div class="code"&gt;&lt;pre&gt;public void reduce(Text key, Iterator values,
                        OutputCollector output, Reporter reporter) throws IOException {
                        
                StringBuilder sb = new StringBuilder();
                sb.append('[');
                while (values.hasNext()) {
                        sb.append('&amp;quot;');
                        sb.append(values.next().toString());
                        sb.append('&amp;quot;');
                        if (values.hasNext())
                                sb.append(',');
                }
                
                sb.append(']');
                outVal.set(sb.toString());
                output.collect(key, outVal);
        }&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Die Ausgabedatei, die der Reducer schreibt ist ca. 300 Mbyte gro&amp;szlig;. Den Abschluss der Vorbereitung ist wieder ein PHP Script, welches pro 10.000 Zeilen der Ausgabedatei einen Batch Request an die CouchDB absetzt. F&amp;uuml;r die 5.700.000 Zeilen, die die Ausgabedatei beseitzt, sind das ca. 600 Sekunden.&lt;/p&gt;
&lt;p&gt;Der abschlie&amp;szlig;ende Prozess ist nun die Zusammenf&amp;uuml;hrung von Produkten und Metadaten. Hierzu gibt es ein Java Projekt, dessen Sourcen ich hier leider nicht zeigen darf ;). Es entstehen HTML Seiten und Link-&amp;uuml;bersichtsseiten, welche der GSA zum Crawling vorgesetzt werden.&lt;/p&gt;
&lt;p&gt;Dieser Crawling Prozess dauert unter Verwendung von CouchDB nur noch ca. 3 Tage statt mehr als 400 Tage. Ein deutlicher Gewinn ;).&lt;/p&gt;&lt;p&gt;Bei n&amp;auml;chster Gelegenheit schreibe ich noch ein FollowUp zusammen, da eine Alternative zu CouchDB auch Redis sein k&amp;ouml;nnte.&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/xml-text-hadoop-couchdb-und-die-google-search"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/xml-text-hadoop-couchdb-und-die-google-search#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/QCaWWMwnh54" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/xml-text-hadoop-couchdb-und-die-google-search</feedburner:origLink></item>
    <item>
      <pubDate>Sun, 26 Jun 2011 11:36:19 -0700</pubDate>
      <title>Kreativität sucht Perspektiven</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/6BcmfeHksr8/kreativitat-sucht-perspektiven</link>
      <guid isPermaLink="false">http://xenji.com/kreativitat-sucht-perspektiven</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Das Sch&amp;ouml;ne an unserem Handwerk ist, dass es so facettenreich ist. Nicht nur die Arbeit, die wir jeden Tag vollbringen, sonder auch die Herangehensweisen an diese Arbeit. Der Eine sieht sich als 9-to-5 - Typ und macht wie ihm aufgetragen wurde. Meist sind diese Menschen fest an einen Wissenstand gebunden und haben "das ja schon immer so gemacht". Um es scherzhaft zu sagen, haben diese Leute einen Horizont, der mit einem Kreis mit dem Radius von null beschrieben werden kann - auch einfach "Standpunkt" genannt. Andere sehen sich als progressiv an, bilden sich weiter und nutzen neue Projekte um es besser zu machen als im Vorherigen. Ich behaupte, dass mit einem Gro&amp;szlig;teil solcher mitarbeiter viele Unternehmen und Agenturen gut &amp;uuml;ber die Runden kommen, jedoch au&amp;szlig;er der Unternehmensgr&amp;ouml;&amp;szlig;e bzw. dem Umsatz, sich nichts Wesentliches bewegt. Wiederum Andere versuchen neues zu schaffen und neue Wege zu beschreiten. Wenn jetzt einigen das Buzzword "innovationsgetrieben" vorschwebt muss ich wahrscheinlich deutlicher werden, da ich es eher als kreativ bezeichne. Nur am oberen Ende der Innovationsleiter zu stehen ist nicht  allein das, was f&amp;uuml;r mich Kreativit&amp;auml;t bedeutet. Kreativit&amp;auml;t ist auch, sich mit der neuen Anwendbarkeit von Bekanntem zu besch&amp;auml;ftigen, Innovationen einflie&amp;szlig;en lassen und einfach den Ansatz von "das haben wir schon immer so gemacht" fallen zu lassen.&lt;/p&gt;&lt;p&gt;Ein gutes Beispiel ist die NoSQL Bewegung. Als falsch empfinde ich es, wenn man nun versucht jede Datenspeicherung in Dokumente, Key-Values, Wide-Columns oder Graphen zu pressen. Hier kann man doch als erstes &amp;uuml;berlegen, was man in der Vergangenheit vielleicht in ein relationales Modell gepresst hat und es darauf hin auf ein passenderes NoSQL Format umstellen. Kreativit&amp;auml;t ist f&amp;uuml;r mich also auch Bestehendes in Frage zu stellen. &lt;/p&gt;&lt;p&gt;Regelm&amp;auml;&amp;szlig;ig treffen in der IT zwei Welten aufeinander. Aus Projektmanagersicht leiden Entwickler am Elfenbeinturm-Syndrom. Alles muss perfekt sein, skalierbar sein. Man will sich mit der guten Arbeit auch profilieren k&amp;ouml;nnen, Stolz empfinden d&amp;uuml;rfen. Der Entwickler jedoch sieht mit einer gewissen Grundangst dem Projektmanager ins Gesicht und wartet darauf, dass Qualit&amp;auml;t zu Gunsten des Preises oder der Zeit minimiert wird oder der kreative Spielraum zu Gunsten einer kosteng&amp;uuml;nstigen und weniger risikobehafteten L&amp;ouml;sung eingeschr&amp;auml;nkt wird. Die Darstellung mag vielleicht &amp;uuml;bertrieben erscheinen, aber das soll sie auch. Risiko ist das Stichwort. Kreative Herangehensweisen sind risikobehaftet und Risiko wird vom Management in Geld gemessen. Beim Thema Finanzen wird es dann meist sehr schnell ruhig. Kreativit&amp;auml;t darf kein Geld kosten - womit sich jegliche Diskussion f&amp;uuml;r mich erledigt. Wenn Kreativit&amp;auml;t und Innovation kein Geld kosten d&amp;uuml;rften, w&amp;uuml;rden wir heute alle noch den VW K&amp;auml;fer der ersten Serie fahren. Der funktionierte doch wunderbar.&lt;/p&gt;&lt;p&gt;Ein Unternehmen muss also die Wahl treffen, ob es kreative Entwickler unterst&amp;uuml;tzt und damit auch Risiken eingeht oder ob es keine zus&amp;auml;tzlichen Risiken eingehen m&amp;ouml;chte und damit die Gefahr eingeht, kreative Entwickler einzuschr&amp;auml;nken und auf Dauer zu verlieren. Also die Leute zu verlieren, die in den Momenten, wo neue Ans&amp;auml;tze gebraucht werden, da sind und vielleicht die z&amp;uuml;ndende Idee haben, die Leute zu verlieren, die einfach Ideen umsetzen die Geld bringen oder Geld sparen k&amp;ouml;nnen. &lt;/p&gt;&lt;p&gt;Klar scheint mir zu sein, dass Vorreiter in der Branche sich nicht durch konservatives Verhalten hervorbringen, es liegt jedoch in der Entscheidung jedes Unternehmens wie ernst es seine sich erdachte Rolle nehmen will.&lt;/p&gt;&lt;p&gt;Kreativit&amp;auml;t sucht Perspektiven.&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/kreativitat-sucht-perspektiven"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/kreativitat-sucht-perspektiven#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/6BcmfeHksr8" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/kreativitat-sucht-perspektiven</feedburner:origLink></item>
    <item>
      <pubDate>Thu, 16 Jun 2011 20:06:17 -0700</pubDate>
      <title>Wenn Autoren es nicht zu Ende bringen</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/gOGrsye4b7c/wenn-autoren-es-nicht-zu-ende-bringen</link>
      <guid isPermaLink="false">http://xenji.com/wenn-autoren-es-nicht-zu-ende-bringen</guid>
      <description>&lt;p&gt;
	&lt;p&gt;In unserer Branche lernt man viel durch Abschauen, durch Lesen und durch Trial &amp;amp; Error. Das Lesen allerdings macht mir in letzter Zeit Probleme - genauer gesagt, das Lesen von Fachb&amp;uuml;chern die eine Einf&amp;uuml;hrung in z. B. ein Framework "X"  oder ein CMS "Y" sein sollen. Meist teilen sich solche B&amp;uuml;cher in einen kurzen Sprachteil (bei Frameworks) oder sonstige Einf&amp;uuml;hrung, dann kommt der Teil, in dem man Laufen lernt. Sp&amp;auml;ter gibts dann noch ein wenig tieferes Wissen und dann ... ? Ende. Wo ist der Teil mit dem Release Management, der Teil &amp;uuml;ber Testing oder der &amp;uuml;ber "Hey, wenn Du das hier im echten Leben einsetzt, dann achte doch mal darauf"? Essenz dessen ist, dass meist der realit&amp;auml;tsnahe Teil auf der Strecke bleibt. Weiterf&amp;uuml;hrende Literatur zu den meisten Themen ergie&amp;szlig;t sich dann &amp;uuml;ber Spezialthemen oder einzelne Teile des CMS, selten findet man jedoch einen Text &amp;uuml;ber "So hab ich es probiert und bin gescheitert, deswegen habe ich es so versucht und es war auch nicht besser", etc. Blogs bieten hier meist Abhilfe, jedoch vergehen diese Perlen h&amp;auml;ufig im Grundrauschen des M&amp;uuml;lls, der im Netz landet. Schade.&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/wenn-autoren-es-nicht-zu-ende-bringen"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/wenn-autoren-es-nicht-zu-ende-bringen#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/gOGrsye4b7c" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/wenn-autoren-es-nicht-zu-ende-bringen</feedburner:origLink></item>
    <item>
      <pubDate>Thu, 09 Jun 2011 20:59:41 -0700</pubDate>
      <title>CouchDB als Import Logger</title>
      <link>http://feedproxy.google.com/~r/xenjicom/~3/DX8YKadhSZ8/couchdb-als-import-logger</link>
      <guid isPermaLink="false">http://xenji.com/couchdb-als-import-logger</guid>
      <description>&lt;p&gt;
	&lt;p&gt;Bei einem unserer eCommerce Kunden besteht die Herausforderung, dass ein Gro&amp;szlig;teil des t&amp;auml;glichen und st&amp;uuml;ndlichen Imports in der Nachweispflicht steht. Hat wohl auch damit zu tun, dass wir aus dem Import durch eine fast perverse Logik allerhand machen sollen. Es ist also unsere Pflich den Import der Artikel und dessen Ergebnis auf nachvollziehbare Art und Weise zu speichern und bei Bedarf Auskunft dar&amp;uuml;ber zu geben. Bisher haben wir dies &amp;uuml;ber Logfiles getan, die sich bei Gr&amp;ouml;&amp;szlig;enordnungen jenseits der Gigabyte Marke als unpraktisch erwisen haben. Mein L&amp;ouml;sungsansatz hei&amp;szlig;t heute ... CouchDB. Die Versionierung der Dokumente kommt dem Vorhaben der Nachweisbarkeit sehr zu Gute. Wir k&amp;ouml;nnen auf Grund der Schl&amp;uuml;ssel, die wir vom ERP Dienstleister geliefert bekommen, sehr gut einen Key f&amp;uuml;r die Dokumente generieren und auf Basis dessen widerum auch die Updates der Artikel als Revisionen in der CouchDB abbilden. Das zugrundeliegende XML wird einfach als Attachment an das Dokument gehanden. Das Attachment hat den Vorteil, dass es durch CouchDB komprimiert werden kann. Insgesamt bietet sich also ein Versionsf&amp;auml;higer, abfragbarer Logger an, der auch durch Projektmanager &amp;uuml;ber Futon bedient werden kann.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Ich find es klasse ;)&lt;/p&gt;
	
&lt;/p&gt;

&lt;p&gt;&lt;a href="http://xenji.com/couchdb-als-import-logger"&gt;Permalink&lt;/a&gt; 

	| &lt;a href="http://xenji.com/couchdb-als-import-logger#comment"&gt;Leave a comment&amp;nbsp;&amp;nbsp;&amp;raquo;&lt;/a&gt;

&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/xenjicom/~4/DX8YKadhSZ8" height="1" width="1"/&gt;</description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1616655/41646_1073854343_8934_n.jpg</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/cPvdSqvQmx3Pc</posterous:profileUrl>
        <posterous:firstName>Mario</posterous:firstName>
        <posterous:lastName>Mueller</posterous:lastName>
        <posterous:nickName>xenji</posterous:nickName>
        <posterous:displayName>Mario Mueller</posterous:displayName>
      </posterous:author>
    <feedburner:origLink>http://xenji.com/couchdb-als-import-logger</feedburner:origLink></item>
  </channel>
</rss>

