<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-764237810137207640</id><updated>2011-11-27T16:00:22.302-08:00</updated><category term='corporate spam'/><category term='dwr'/><category term='mailing lists'/><category term='hibernate'/><category term='TDD'/><category term='LOP'/><category term='DSL'/><category term='spring'/><category term='rss'/><category term='DRY'/><category term='junit'/><category term='subclipse springsource ganymede eclipse mac leopard'/><category term='syntax'/><category term='subclipse'/><category term='springingetration'/><title type='text'>lazy log</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>31</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-3874491188971393532</id><published>2011-07-25T07:38:00.001-07:00</published><updated>2011-07-25T07:38:50.074-07:00</updated><title type='text'>Logback hack to log different levels in the same package to different appenders</title><content type='html'>&lt;div class='posterous_autopost'&gt;Given the long title you could think that this is going to be a blog about a ridiculous edge case. It isn't, honestly! It is a blog about an edge case, but not ridiculous and not as far fetched as you think. Let's say that you have a class logging on DEBUG and TRACE. The debug messages contain (frequent) checks, but lack the full information needed to analyze the problem. This information (say a full xml message) is logged on TRACE level. Now your friendly system administrator decides that he needs this trace logging to go into a different file from the debug logging. He has good arguments and you don't want to pick a fight. Logback provides a lot of configuration options that you can do lots of neat things with. But it can't fill this requirement. Really? Well, there is a hack.&lt;p /&gt;&lt;div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Setting up the experiment&lt;/div&gt;&lt;div&gt;-----------------------------------&lt;/div&gt;&lt;div&gt;Logback works with appenders and loggers. Appenders define where output goes and how it is formatted. Loggers define where logs come from and which appenders should be used to write to.&amp;nbsp;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;So if we want to log to a certain appender on a certain level we create a logger like this.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;div class="data type-xml"&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;/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;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;logger&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;iwein.samples.foo&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;appender-ref&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT1&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;trace&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;appender-ref&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT2&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;debug&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/logger&amp;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;/div&gt;&lt;p /&gt;&lt;div&gt;The appender totally standard, but I'll include it anyway.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;div class="data type-xml"&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;/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;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;appender&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT1&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ch.qos.logback.core.ConsoleAppender&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;layout&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ch.qos.logback.classic.PatternLayout&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;Pattern&amp;gt;&lt;/span&gt;STDOUT2 %logger{36} - %msg%n&lt;span class="nt"&gt;&amp;lt;/Pattern&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/layout&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/appender&amp;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;/div&gt;&lt;p /&gt;&lt;div&gt;The logging is done in a class in the package 'iwein.samples.foo', again just adding it for completeness.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;div class="data type-java"&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;/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="kn"&gt;package&lt;/span&gt; &lt;span class="n"&gt;iwein&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;samples&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="o"&gt;;&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="c1"&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SomeLoggingThing&lt;/span&gt; &lt;span class="o"&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="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;LoggerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SomeLoggingThing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC8"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;saySomething&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC9"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;INFO&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC10"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;DEBUG&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC11"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;trace&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;TRACE&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC12"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC13"&gt;&lt;span class="o"&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;/div&gt;&lt;p /&gt;&lt;div&gt;I wrapped this in a testcase, but if you want all the code you'll just have to [grab it](&lt;a href="https://github.com/iwein/logback-testdrive/commit/1b543645dc561ebb81237238d5698d95c34d4f4f"&gt;https://github.com/iwein/logback-testdrive/commit/1b543645dc561ebb81237238d5698d95c34d4f4f&lt;/a&gt;). &amp;nbsp;We now have the basic position from which the interesting stuff can start. Let's try to implement the requirement next.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;First attempt: multiple appender-refs&lt;/div&gt;&lt;div&gt;-------------------------------------------------&lt;/div&gt;&lt;div&gt;We want our logger that is created in the java code up there to log to different appenders. You can do this by adding an appender ref, but we also want to log with different levels to different appenders. That's a little harder.&lt;/div&gt;&lt;div&gt;&lt;div class="data type-xml"&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;/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;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;logger&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;iwein.samples.foo&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;trace&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;appender-ref&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT1&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;appender-ref&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT2&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/logger&amp;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;/div&gt;&lt;p /&gt;&lt;div&gt;If I did the domain model for logback (which I didn't), the appender-ref would correspond to an object, on which the log level would be set. In reality, logback allows you to set a level on the logger, so one logger only has one level. Would be nice if you could do something like this:&lt;/div&gt;&lt;div&gt;&lt;div class="data type-xml"&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;/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;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;logger&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;iwein.samples.foo&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;appender-ref&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT1&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;trace&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;appender-ref&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT2&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;debug&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/logger&amp;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;/div&gt;&lt;p /&gt;&lt;div&gt;Which you can't... which is a bummer.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Second attempt: multiple loggers&lt;/div&gt;&lt;div&gt;--------------------------------------------&lt;/div&gt;&lt;div&gt;Now conceptually, if you add another logger, you could use a different level there and a different appender too: problem solved, TADA! So let's try.&lt;/div&gt;&lt;div&gt;&lt;div class="data type-xml"&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;/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;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;logger&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;iwein.samples.foo&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;trace&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;appender-ref&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT1&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/logger&amp;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;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;logger&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;iwein.samples.foo&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;level=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;debug&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;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="nt"&gt;&amp;lt;appender-ref&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT2&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/logger&amp;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;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;a href="https://gist.github.com/1104212"&gt;&lt;/a&gt;When I run this in my test the output is:&lt;/div&gt;&lt;div&gt;STDOUT2 iwein.samples.foo.SomeLoggingThing - INFO&lt;/div&gt;&lt;div&gt;STDOUT1 iwein.samples.foo.SomeLoggingThing - INFO&lt;/div&gt;&lt;div&gt;STDOUT2 iwein.samples.foo.SomeLoggingThing - DEBUG&lt;/div&gt;&lt;div&gt;STDOUT1 iwein.samples.foo.SomeLoggingThing - DEBUG&lt;/div&gt;&lt;p /&gt;&lt;div&gt;What happens is that there is only one logger in the end with two appenders and its level set to the last logger loaded. Kraznoks!&amp;nbsp;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;After some headscratching we came up with another solution. It isn't pretty, but it's the first one to actually do the job.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Third attempt: filter in the appender&lt;/div&gt;&lt;div&gt;-----------------------------------------------&lt;/div&gt;&lt;div&gt;Before you run away screaming, let me assure you that I know this isn't how it _should_ work, but it's the only way I could come up with so far. I'll log an improvement request in the logback issue tracker of course.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;So how about you log to both appenders, but filter out the trace messages you don't want in one appender? That would work...&lt;/div&gt;&lt;p /&gt;&lt;div&gt;The downside is though that I had to make my appender look like this:&lt;/div&gt;&lt;div&gt;&lt;div class="data type-xml"&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;/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;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;appender&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;STDOUT2&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ch.qos.logback.core.ConsoleAppender&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;filter&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ch.qos.logback.core.filter.EvaluatorFilter&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;evaluator&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator --&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;expression&amp;gt;&lt;/span&gt;return Level.TRACE.equals(Level.toLevel(level)) &lt;span class="ni"&gt;&amp;amp;amp;&amp;amp;amp;&lt;/span&gt; logger.startsWith(&amp;quot;iwein.samples.foo&amp;quot;);&lt;span class="nt"&gt;&amp;lt;/expression&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/evaluator&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC6"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;OnMismatch&amp;gt;&lt;/span&gt;NEUTRAL&lt;span class="nt"&gt;&amp;lt;/OnMismatch&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;OnMatch&amp;gt;&lt;/span&gt;DENY&lt;span class="nt"&gt;&amp;lt;/OnMatch&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC8"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/filter&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC9"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;layout&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ch.qos.logback.classic.PatternLayout&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC10"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;Pattern&amp;gt;&lt;/span&gt;STDOUT1 %logger{36} - %msg%n&lt;span class="nt"&gt;&amp;lt;/Pattern&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC11"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/layout&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC12"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="nt"&gt;&amp;lt;/appender&amp;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;/div&gt;&lt;p /&gt;&lt;div&gt;Which is nothing short of an abomination. See&amp;nbsp;&lt;a href="http://jira.qos.ch/browse/LBCLASSIC-284"&gt;http://jira.qos.ch/browse/LBCLASSIC-284&lt;/a&gt;&amp;nbsp;for progress on this issue.&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/logback-hack-to-log-different-levels-in-the-s"&gt;Iwein's braindumps&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-3874491188971393532?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/3874491188971393532/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=3874491188971393532' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3874491188971393532'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3874491188971393532'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2011/07/logback-hack-to-log-different-levels-in.html' title='Logback hack to log different levels in the same package to different appenders'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-2528065192826846926</id><published>2011-05-09T02:26:00.001-07:00</published><updated>2011-05-09T02:26:47.987-07:00</updated><title type='text'>Found in the wild: uncertainty</title><content type='html'>&lt;div class='posterous_autopost'&gt;Let met just keep this short and let the code speak for itself:&lt;p /&gt;&lt;div&gt;&lt;div class="data type-java"&gt;  &lt;table 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;/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;&amp;nbsp;&amp;nbsp;&lt;span class="c1"&gt;// The next fields counts the number of time the decide method is called&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="c1"&gt;//&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="c1"&gt;// IMPORTANT: This field can be updated by multiple threads. It follows that&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="c1"&gt;// its values may *not* be incremented sequentially. However, we don&amp;#39;t care&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="c1"&gt;// about the actual value of the field except that from time to time the&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC6"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="c1"&gt;// expression (invocationCounter++ &amp;amp; 0xF) == 0xF) should be true.&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;invocationCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC8"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;&lt;/div&gt;   &lt;/td&gt; &lt;/tr&gt; &lt;/table&gt;  &lt;/div&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Three letters apply here.&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/found-in-the-wild-uncertainty"&gt;Iwein's braindumps&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-2528065192826846926?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/2528065192826846926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=2528065192826846926' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2528065192826846926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2528065192826846926'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2011/05/found-in-wild-uncertainty.html' title='Found in the wild: uncertainty'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-4744328824932220676</id><published>2011-03-22T02:19:00.001-07:00</published><updated>2011-03-22T02:19:28.082-07:00</updated><title type='text'>Confession of a developer junkie</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;p&gt;I like &lt;a href="http://sethgodin.typepad.com/seths_blog/2010/08/splitting-wood.html"&gt;splitting wood&lt;/a&gt;. It’s a simple physical activity and I’m good at it. I can tell you exactly why I like splitting wood; it is very similar to why I like doing some other things, like building software for example. There has been a &lt;a href="http://serialseb.blogspot.com/2009/03/why-im-not-signing-software.html"&gt;lot&lt;/a&gt; of &lt;a href="http://martinfowler.com/bliki/CraftmanshipAndTheCrevasse.html"&gt;discussion&lt;/a&gt; in software development about this thing some people call &lt;a href="http://www.joelonsoftware.com/articles/Craftsmanship.html"&gt;craftsmanship&lt;/a&gt;&lt;object height="417" width="500"&gt;&lt;param name="movie" value="http://www.youtube.com/v/soOJDRlRUQM&amp;hl=en&amp;fs=1" /&gt;&lt;/param&gt;&lt;param name="wmode" value="window" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/soOJDRlRUQM&amp;hl=en&amp;fs=1" allowfullscreen="true" type="application/x-shockwave-flash" allowscriptaccess="always" wmode="opaque" height="417" width="500"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;  &lt;p&gt;When you split a log (assuming you have a decent tool) things are quite simple. There are a lot of physics involved, like the direction of the grains, the cohesion between them. The moisture is important too, the momentum of the axe, the angle… But when I swing I don’t think of those. I just look at the log, know where I want to hit it and then it happens the way I saw it in my head. It doesn’t always go right, but it does a lot of times. When it goes right I know it before I register it. Right at the moment the axe has its maximum momentum and the direction is set I know there is nothing to correct and the scenario can play out the way it should. And then there is the moment when the axe hits the wood and sinks in effortlessly. There is the well articulated “chk” immediately followed by a “pang” as the tension makes the log snap apart. If you hit as hard as you can you will send two parts flying away, but that doesn’t give me most satisfaction. I like it when I hit just hard enough and two parts end up standing next to each other. I can immediately go on and take another swing without stooping over and straightening the logs. That feeling is the most addictive thing I’ve found in life. I can continue splitting wood far beyond comfort, just to get another fix of that feeling. I am not alone in this I believe.&lt;/p&gt;  &lt;p&gt;A long time friend of mine is a baseball player. He told me a similar story about hitting a ball just right. The pitcher throws, not too slow, but you catch the ball with your eye. You swing at it and as the bat cuts through the air, you know it’s going to connect right. Then the ball hits the bat so that you hardly feel it. You just year the “ping” and you know it’s a home run. I’m not a baseball player, but apparently there is nothing like that feeling. I believe it is the same feeling that I get from splitting logs.&lt;/p&gt;  &lt;p&gt;A related thing has been described before by Csíkszentmihályi Mihály. It is referred to as “Flow” or “The Zone”. If you haven’t seen Csíkszentmihályi’s work you definitely should have a look (feel free to copy paste now to avoid spelling errors). I believe this immediate feeling of joy as you do something right lies at the basis of flow.&lt;/p&gt;  &lt;p&gt;With some effort I can get this feeling when developing software too. It is even possible to share this feeling with a whole team of developers. When that happens I love my job so much I’d do it for free until I starve. With some more effort it is possible to do this on a project that actually delivers business value to a customer. This means I can do this great thing without starving if I play my cards right. I need a way to get the people that stop me from doing this to get a clue and let me do my thing. You probably know the types I’m talking about: it’s the manager up high that makes me work on a virtual desktop that runs vista; it’s the architect that forces me to use a five year old version of a bad framework and makes me deploy to Weblogic 5; it’s the customer that waves three years old specs at me when I ask him a question about how he wants you to implement a feature. It is also the colleague that refuses to talk to me about my real problem if it is not related to cool new obscure technology X that somebody blogged about this morning.&lt;/p&gt;  &lt;p&gt;If I can get these people to grow up by talking to them about Agile, XP, or Craftsmanship, or Lean, or Oompa Loompa’s; I will do it. I’m a junky remember? I want to get my daily flow fix! When Robert Martin said we were tired of writing crap, it didn’t ring true with me. I’m not tired of it at all. I’m prepared to write a lot of crap to get it right just once. If we do have a nice bit of marketing on the word craftsmanship I’m fine to surf that wave for now. Next year we’ll call it Real Engineering, the year after Real Development. Why the hell not. As long as some of us get what it is about and they are in my team I’m totally cool with it.&lt;/p&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/confession-of-a-developer-junkie"&gt;Iwein's braindumps&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-4744328824932220676?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/4744328824932220676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=4744328824932220676' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/4744328824932220676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/4744328824932220676'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2011/03/confession-of-developer-junkie.html' title='Confession of a developer junkie'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-2735811466497783792</id><published>2011-03-22T02:04:00.001-07:00</published><updated>2011-03-22T02:04:58.904-07:00</updated><title type='text'>Ja tegen proteïnen, nee tegen vieze shakes</title><content type='html'>&lt;div class='posterous_autopost'&gt;Ongeveer een half jaar geleden kreeg ik last van mijn rug. Het advies van de dokter en fysiotherapeut was om zo veel mogelijk te bewegen en zo weinig mogelijk achter de computer te zitten. Omdat ik vastbesloten was, mijn rug (en buik) zo snel mogelijk in vorm te krijgen, heb ik het advies opgevolgd. Deze blog heeft daar enigszins onder geleden, maar omdat ik nu een slanke en fitte dertiger ben, mag ik weer lekker lang achter mijn computer zitten ;-). &lt;p /&gt; Gezond eten en regelmatig bewegen zijn onmisbaar om een gezond lijf te krijgen en te houden. Als je eenmaal lekker aan het bewegen bent geslagen, wordt het een sport om steeds iets meer te tillen en langer door te gaan. Op het feestje van Wouter, kwam &lt;a href="http://www.fourhourbody.com/"&gt;The four hour body&lt;/a&gt;&amp;#39; ter sprake. Om een goddelijk lijf te krijgen hoef je volgens Timothy Ferriss slechts 4 keer in een maand te trainen en moet je 100 gram extra eiwitten per dag eten. Als je bedenkt dat er in een &lt;a href="http://www.weightlossforall.com/protein_content_from_good_source.htm"&gt;eitje hooguit 7 gram proteïne&lt;/a&gt; zit, moet je dus al gauw 14 eieren per dag eten... Ze zijn niet gemakkelijk weg te werken, want eieren vullen goed. Je  gaat van eieren enorm stinken. Bovendien is een eenzijdig dieet niet gezond. Dus op welke andere manier krijg je dan 100 gram proteïnen per dag extra binnen?&lt;p /&gt; &lt;a name='more'&gt;&lt;/a&gt;&lt;p /&gt;&lt;object height="417" width="500"&gt;&lt;param name="movie" value="http://www.youtube.com/v/LLk4rsCNFFU&amp;hl=en&amp;fs=1" /&gt;&lt;/param&gt;&lt;param name="wmode" value="window" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/LLk4rsCNFFU&amp;hl=en&amp;fs=1" allowfullscreen="true" type="application/x-shockwave-flash" allowscriptaccess="always" wmode="opaque" height="417" width="500"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p /&gt;Een eenvoudige, maar niet bepaald prettige manier, is het drinken van &lt;a href="http://nl.wikipedia.org/wiki/Weiprote%C3%AFne-concentraat"&gt;weipoeder shakes&lt;/a&gt;. Je haalt zo gemakkelijk je quotum, maar er kleven nogal wat nadelen aan:&lt;br /&gt; &lt;ul&gt;&lt;li&gt;door de proteïnen verdwijnt je hongergevoel, daardoor is het lastig om voldoende gezond voedsel te blijven eten,&lt;/li&gt;&lt;li&gt;je kunt er vreselijk verstopt van raken dus je moet extra vezels eten, maar je had al minder honger dus dat is een hele opgave,&lt;/li&gt; &lt;li&gt;het is hartstikke vies. De paar slokken die ik geproefd heb, waren meteen de allerlaatste. Op het kokhalsen na werd ik niet ziek, maar drie keer per dag een halve liter drinken is me echt te gortig. &lt;/li&gt;&lt;/ul&gt;Dus weipoeder wordt het liever niet.&lt;p /&gt; &lt;div&gt;Hoe krijg je op een gezonde &lt;i&gt;en prettige&lt;/i&gt; manier 100 gram proteïnen per dag extra binnen?&lt;p /&gt;&lt;/div&gt;&lt;div&gt;Eerder zijn de 14 eieren al voorbij gekomen. Er zijn verschillende gerechten te vinden om eieren makkelijker verteerbaar en lekkerder te maken. Voeg steeds verschillende groenten en verse kruiden toe en je hebt een heel andere smaaksensatie. Kijk bijvoorbeeld even naar mijn Thaise omelet. Het vullende effect van de eieren is hiermee nog niet opgelost. Dus om je quotum te halen moet je ook:&lt;br /&gt; &lt;ul&gt;&lt;li&gt;de hoeveelheid koolhydraten in je dieet limiteren (minder pasta, rijst en brood),&lt;/li&gt;&lt;li&gt;langzame koolhydraten eten en vooral geen snelle (geen snoep, maar brood),&lt;/li&gt;&lt;li&gt;vaak sporten,&lt;/li&gt;&lt;li&gt;proteïnen en vetten eten om je honger na het sporten te stillen,&lt;/li&gt; &lt;li&gt;granen en fruit voor en tijdens het sporten eten,&lt;/li&gt;&lt;li&gt;je eten over meer maaltijden verdelen.&lt;/li&gt;&lt;/ul&gt;Andere overheerlijke gerechten met veel proteïnen: &lt;p /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"&gt; &lt;b&gt;Gerookte zalm met mierikswortelmayonaise&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;Tegenwoordig vind je in bijna ieder restaurant wel een visgerecht met wasabi. Het zou dan ook saai zijn om op deze blog een recept met wasabi te geven. In plaats van wasabi gebruik ik mierikswortel (wasabi en mierikswortel zijn broertjes). Mierikswortel heeft een scherpe smaak die op mosterd lijkt.  Mierikswortel is in de gewone supermarkt in een potje te verkrijgen, maar je kunt het ook &lt;a href="http://www.de-natuur.be/pages/mierikswortel.html"&gt;mierikswortel zelf kweken&lt;/a&gt;. Waarschuwing: in tegenstelling tot wasabi groeit mierikswortel in Nederland fantastisch, je krijgt het nooit meer uit je tuin.&lt;br /&gt; &lt;/blockquote&gt;&lt;ul /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;100g gerookte zalm (laten we niet kinderachtig doen)&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;wat rauwkost naar smaak (veldsla doet het goed, maar ook ijsbergsla of komkommer is er lekker bij)&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;3 eetl. mayonaise (mag je zelf maken, of niet natuurlijk)&lt;/i&gt;&lt;/li&gt; &lt;li&gt;&lt;i&gt;1 eetl. gemalen mierikswortel&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;beetje verse dille&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;&lt;blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"&gt;&lt;div&gt;Meng de mierikswortel, de mayonaise en de dille in een kommetje, zodat het een lekker sausje wordt. Leg de zalm op een bord en serveer de saus en rauwkost erbij.&lt;/div&gt; &lt;/blockquote&gt;&lt;div&gt;&lt;br /&gt;Als je dan zo&amp;#39;n lekker stukje zalm op hebt dan kun je er vast nog wel een biefstuk bijhebben:&lt;p /&gt;&lt;/div&gt;&lt;p /&gt;&lt;blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"&gt; &lt;div&gt;&lt;b&gt;Biefstuk op spinazie met lijnolie tobasco dressing&lt;/b&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Neem een goede biefstuk. De Marqt is prima, maar er zijn ook redelijke biefstukken in de schappen van de supermarkt te vinden, neem vooral niet de lichtroze geverfde kiloknallers.&lt;/div&gt; &lt;/blockquote&gt;&lt;div&gt;&lt;ul /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;1 biefstuk&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;200g verse spinazie&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;scheutje lijnzaadolie&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;i&gt;tobasco naar smaak&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"&gt; &lt;div&gt;Plaats een bord in de oven en verwarm de oven voor op 75 graden Celsius. Braad de biefstuk in weinig boter of een beetje rijstolie rondom snel aan. Haal hem uit de pan en leg hem ingepakt in aluminiumfolie op je bord in de oven. Gooi de spinazie om in de nog hete pan, totdat alle blaadjes slap geworden zijn (duurt ongeveer 2 minuten). Haal je bord en de biefstuk uit de oven en leg de spinazie op het voorverwarmde bord.  Leg de biefstuk op het spinazienestje,  schenk er de lijnzaadolie en tabasco over.&lt;/div&gt; &lt;/blockquote&gt;&lt;div&gt;&lt;br /&gt;Met deze twee gerechten heb je dus het equivalent van 8 eieren te pakken. In vis zit namelijk ongeveer 25 gram proteïnen per 100 gram, daarbij zitten er Omega 3 en 6 vetzuren in die erg goed schijnen te zijn tegen hart en vaatziekten. In biefstuk zit ongeveer 28 gram proteïnen per 100 gram. Het mooie is dat je van dit soort gerechten lang niet zo&amp;#39;n vol gevoel krijgt als van 8 eieren. Ik kan het in ieder geval prima vóór mijn avondmaaltijd wegwerken. Als je bij de lunch nog een omelet eet, heb je de extra proteïnen al bijna te pakken.  &lt;p /&gt; Als je geld genoeg hebt en een goeie visboer in de buurt, kun je de rest mooi met oesters aanvullen :).&lt;p /&gt;Eet smakelijk!&lt;/div&gt;&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://eten.posterous.com/ja-tegen-proteinen-nee-tegen-vieze-shakes"&gt;Koken en Eten&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-2735811466497783792?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/2735811466497783792/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=2735811466497783792' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2735811466497783792'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2735811466497783792'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2011/03/ja-tegen-proteinen-nee-tegen-vieze.html' title='Ja tegen proteïnen, nee tegen vieze shakes'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-3660813594649909023</id><published>2011-02-26T09:12:00.001-08:00</published><updated>2011-02-26T09:12:05.653-08:00</updated><title type='text'>Curing distributed Agile Illnesses: Diagnosis</title><content type='html'>&lt;div class='posterous_autopost'&gt;In my session on 'When Agile Offshoring fails' at&amp;nbsp;&lt;a href="http://www.agilencr.org/"&gt;AgileNCR&lt;/a&gt;&amp;nbsp;this Saturday I decided to harvest ideas from the attendees on different illnesses. The results were beyond my expectations; in this blog I will share a few of them and give a few preliminary comments on the result. The general plan is described better with the following diagram.&lt;p /&gt;&lt;div&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/rzAb4IHxcL39ZT7XzfKNeqWlrIWFPEVotOu1bM42uLlSDUtt9qKqYXWUpwUC/diagnosis-agile-failure.png'&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iweinfuld/sSLlVeiCoIcJWwooUb1DwouUEOhZi0ANq2UBEXlikiatn8zhDCDeRVCfxaa0/diagnosis-agile-failure.png.scaled.500.jpg" width="500" height="285"/&gt;&lt;/a&gt; &lt;/div&gt;&lt;div&gt;First I would ask the attendees to come up and write down all the symptoms related to failing distributed agile teams on a sticky. These we put on one part of the walls of the room. Then I would ask them to write causes for symptoms on stickies and put them on another part of the wall. Finally we would all try to come up with a possible mitigation for each cause. It worked beautifully, let me show you.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;a name='more'&gt;&lt;/a&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Interestingly I intended to do in this session exactly what Olav would be urging for the first day of the conference: analyze agile failures so we can inspect and adapt and become more effective. But let me get to some details before I give up and fall asleep.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;The following is a (very poor) picture that I took of my hotel wall after rearranging the stickies I had stuffed in my bag.&amp;nbsp;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/D7S42Ubllz5VJPNIvRxA4RxKKvDOp1j78V9P2M7exU5vh9FY7Sr7fksHglye/2011-02-26_21.58.32.jpg.scaled.1000.jpg'&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iweinfuld/Wg6sin9vNJgdc11pxwI0gIVmUVtK8NMN1hC3gipwHORP3USb8FPhGh9NmUTH/2011-02-26_21.58.32.jpg.scaled.500.jpg" width="500" height="375"/&gt;&lt;/a&gt; &lt;/div&gt;&lt;p /&gt;&lt;div&gt;Now that I have this, the real work can begin. First I will look at the causes and cures to see what fits with what, sift out the duplicates and see if I can formulate a couple of likely experiments. Then I intend to formulate a challenge and post that at the&amp;nbsp;&lt;a href="http://blog.xebia.com/"&gt;Xebia blog&lt;/a&gt;.&amp;nbsp;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;One attendee commented (and rightfully so) that it was a bit ungratifying that we didn't come to a full conclusion after the session. There's no closure here for sure. While the intent of the session was to sparkle the interest as opposed to satisfying the attendees, there is no reason to be mean. Here are a few highlights that I can see through the fog already:&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;ul class="MailOutline"&gt;&lt;li&gt;Frequent co-location is mentioned the most as a solution by far, it mitigates whole bunch of problems&lt;/li&gt;&lt;li&gt;By far the most problems evolve around exchanging information, but a remarkable second is trust&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;p /&gt;&lt;/div&gt;&lt;div&gt;One other interesting thought that keeps nagging at me is that many of the listed symptoms and causes are reenforced by larger team sizes. This is the case with both co-located teams and distributed teams, but because the mitigation here is usually sought in colocation I am inclined to consider that in co-location larger team sizes are possible than in distributed team. &amp;nbsp;Given the other factor that co-location is expensive, this poses an interesting optimization problem that only in certain particular configurations distributed teams are more cost effective than co-located teams. It would be great to get some data on this...&lt;/div&gt;&lt;p /&gt;&lt;div&gt;I'm now torn between digitizing the&amp;nbsp;&lt;a href="http://linoit.com/users/iwein/canvases/distributed-agile-medicine"&gt;cards on linoit&lt;/a&gt;&amp;nbsp;and my bed. I'm affraid the bed is winning at the moment. I hope you enjoyed this, stay tuned for more analysis.&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/curing-distributed-agile-illnesses-diagnosis"&gt;Iwein's braindumps&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-3660813594649909023?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/3660813594649909023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=3660813594649909023' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3660813594649909023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3660813594649909023'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2011/02/curing-distributed-agile-illnesses.html' title='Curing distributed Agile Illnesses: Diagnosis'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-2497793529135782012</id><published>2011-01-20T08:23:00.001-08:00</published><updated>2011-01-20T08:23:25.209-08:00</updated><title type='text'>Easy peasy websockets with node.js and socket.io</title><content type='html'>&lt;div class='posterous_autopost'&gt;With our Web Sockets incubator we had a&amp;nbsp;&lt;a href="http://app-incubator.xebia.com/some-quick-experiments-with-web-sockets-using#more"&gt;rough start on Atmosphere&lt;/a&gt;&amp;nbsp;grinding through the samples. There is no intention to bash Atmosphere, it looks like an interesting approach. However, it should be a lesson to all aspiring framework builders out there: getting your samples in top shape matters a lot. This week we tried out socket.io and I wasn't too hopeful as I had planned all kinds of things throughout the evening. The result of a 40 minute pairing session with&amp;nbsp;&lt;a href="http://sonnygill.net/"&gt;Sonny Gill&lt;/a&gt;&amp;nbsp;was pretty good and I'll share the basic highlights here in a very short post.&lt;p /&gt;&lt;div&gt;First we installed node.js and used npm to install socket.io. Next we moved on to create a simple app that exposes a socket on the server. Finally we created a client that opens a socket and sends some test string over the wire.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;The code you can find on github as usual:&amp;nbsp;&lt;a href="https://github.com/xebia/app-incubator-web-sockets/blob/master/socketio-sample"&gt;https://github.com/xebia/app-incubator-web-sockets/blob/master/socketio-sample&lt;/a&gt;. All in all it is less than 50 lines of javascript and html and it simply works as expected. Not bad for less than an hour of fiddling! In our next session we'll look into the possibilities of streaming video over Web Sockets, or maybe we will look at another framework to see if it performs any more interesting magic tricks. That's all for now, stay tuned!&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://app-incubator.xebia.com/easy-peasy-websockets-with-nodejs-and-socketi"&gt;Xebia App Incubator&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-2497793529135782012?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/2497793529135782012/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=2497793529135782012' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2497793529135782012'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2497793529135782012'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2011/01/easy-peasy-websockets-with-nodejs-and.html' title='Easy peasy websockets with node.js and socket.io'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-8653318572792331598</id><published>2011-01-11T01:36:00.001-08:00</published><updated>2011-01-11T01:36:26.984-08:00</updated><title type='text'>Force breakthrough by forcing mistakes</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;div&gt;A week or so ago I started to play&amp;nbsp;&lt;a href="http://www.appbrain.com/app/math-workout-sale/net.mathsworkout"&gt;Math Workout&lt;/a&gt;&amp;nbsp;to rekindle my degenerated calculation skills. After a while I got stuck at a certain speed, making no mistakes anymore. I tried to push myself to go faster, but without making mistakes but that just didn't work. Then I tried a different approach: I forced myself to go fast, mistakes or no. After a couple of sessions, I went back to making no mistakes and to my surprise I was around 8% faster. I have a theory about why this is and I'm applying it to life without hesitation from now on, so read on if you want to share the fun.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&amp;lt;!-- more --&amp;gt;&lt;/div&gt;&lt;div style="font-size: 13px;"&gt;&lt;b&gt;What's Math Workout&lt;/b&gt;&lt;/div&gt;&lt;div&gt;I'll give you some background on Math Workout first, so you can understand the example. Math Workout is a game that let's you solve simple calculations and times you while you do so. The main goal is to be as fast as you can. For example, on easy level the hardest addition is 8&amp;#43;7 and the hardest multiplication is 4*6 (I'm considering 5*6 easier). Dead easy as you can see. The trick though is that you need to solve 20 of these problems in less than 23 seconds, and I can tell you that's tricky enough because you need to read the problem, come up with the answer and type it correctly in about a second.&lt;/div&gt;&lt;p /&gt;&lt;div style="font-size: 13px;"&gt;&lt;b&gt;What goes wrong if you don't make mistakes&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Somehow I got into a rhythm. See the numbers, see the operator, answer pops up, type it. There are probably a few more steps that I was doing unconsciously, but the point is that I was taking a fixed amount of time for each step. Sometimes I found myself breaking the rhythm just before I punched the wrong number and then taking some fixed amount of time again to correct myself. Whenever that didn't happen my time would be between 26 and 27 seconds consistently. Basically I had put a few safety checks in (which I probably didn't need most of the time) that were slowing me down. Whenever I pushed myself, I would occasionally parse the wrong operator, type the wrong number, pop up the wrong answer and quickly revert to the strategy that worked. Once I noticed this, I knew I needed to break the pattern.&lt;/div&gt;&lt;p /&gt;&lt;div style="font-size: 13px;"&gt;&lt;b&gt;Forcing errors&lt;/b&gt;&lt;/div&gt;&lt;div&gt;I decided to change the pattern, and ignore the mistakes at first. I decided to ignore the operator check and assume that my brain would be able to pick up the numbers and the operator in one go. I made 5 errors out of 20 questions and decided that I was bad at picking the operator, but it must be working somehow, otherwise I would have seen more in the range of 10 mistakes. I gave myself positive feedback by thinking I was a smart cookie for figuring that out. &amp;nbsp;I repeated it a few times and saw the errors go down and the times with it, more positive feedback. After a mere 5 runs I focussed on making no mistakes again, and I was below 25 seconds. Mind you, before that, trying for over 50 runs there was no way in hell that I was going to go under 26, my top times were averaging around 27.5 seconds. By forcing the errors I had broken the pattern and found a more optimum way of behaving. &lt;b&gt;Much faster&lt;/b&gt;&amp;nbsp;than waiting for some luck would have done.&lt;/div&gt;&lt;p /&gt;&lt;div style="font-size: 13px;"&gt;&lt;b&gt;What's going on here&lt;/b&gt;&lt;/div&gt;&lt;div&gt;When you make a mistake you tend to give yourself negative feedback &amp;quot;aww shoot!&amp;quot; and this tells you to avoid the behavior that led to this the next time. When you don't make mistakes and you have a better time than before you give your self positive feedback and reinforce the behavior that led to the result. When you try something new and it doesn't pay off immediately, you will give yourself negative feedback. We crave positive feedback, so we keep on aiming to get that result improving, even if our method is flawed and we're in the wrong rhythm. It's hard to break a pattern that reasonable results but is suboptimal. The main reason here is that when left to it's own self learning devices, the variation in methods goes down rapidly. It takes a conscious effort or a lucky coincidence to break out of the suboptimum. The lucky coincidence becomes less and less likely the more you reinforce the suboptimal behavior. This is caused by a thing called&amp;nbsp;&lt;a href="http://youarenotsosmart.com/2010/07/07/extinction-burst/"&gt;Extinction Burst&lt;/a&gt;&amp;nbsp;which is intended to pulls you back into the behavior that worked in the past.&lt;/div&gt;&lt;p /&gt;&lt;p /&gt;&lt;p&gt;       &lt;div style='padding: 5px 5px 10px 5px; margin-top: 5px; border: 1px solid #ddd; background-color: #fff;line-height: 16px;'&gt;       &lt;div style="float: left; margin-right: 5px; overflow: visible;"&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/HhSDmxoicZzVgeyCozLRlTEJuVrgp12R9rCPmcUlJt3yE1CGBNzOOWnRxyxL/PastedGraphic-3.pdf' style='color: #bc7134;'&gt;&lt;img src='http://posterous.com/images/filetypes/pdf.png' style='border: none;'/&gt;&lt;/a&gt;&lt;/div&gt;       &lt;div style="font-size: 10px; color: #424037;line-height: 16px;"&gt;Download now or &lt;a href='http://iweinfuld.posterous.com/force-breakthrough-by-forcing-mistakes' style='color: #bc7134;'&gt;preview on posterous&lt;/a&gt;&lt;/div&gt;       &lt;b&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/HhSDmxoicZzVgeyCozLRlTEJuVrgp12R9rCPmcUlJt3yE1CGBNzOOWnRxyxL/PastedGraphic-3.pdf' style='color: #bc7134;'&gt;PastedGraphic-3.pdf&lt;/a&gt;&lt;/b&gt; &lt;span style="font-size: 10px; color: #424037;"&gt;(21 KB)&lt;/span&gt;       &lt;br style="clear: both;"/&gt;&lt;/div&gt;      &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p /&gt;&lt;div style="font-size: 13px;"&gt;&lt;b&gt;What's to learn?&lt;/b&gt;&lt;/div&gt;&lt;div&gt;It pays off to try things, even if the first results are not impressive follow through for a bit and see if you might just be crossing a chasm and things are better on the other side. I've seen this pattern not only in my own behavior, but also in the behavior of groups of students and teams of software developers. As long as we didn't plot the graph of all possibilities the only way to find out that behavior is suboptimal is to explore and find a better type of behavior. With Math Workout this is easy, because if I can't make the required time my behavior must be the problem. If there is no required time and nobody knows which goals to set (like in Software development, or any kind of creative work really) you can never be sure of what works best until you've literally tried everything. The trick is to find a way to reward yourself for trying the new thing that doesn't relate too much to the old reward of squeezing every last drop out of a poor method.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;I'm not saying you should be trying everything right now, but how about trying one thing each week? That would already be a huge improvement for most of us I'm sure.&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/force-breakthrough-by-forcing-mistakes"&gt;Iwein's braindumps&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-8653318572792331598?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/8653318572792331598/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=8653318572792331598' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/8653318572792331598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/8653318572792331598'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2011/01/force-breakthrough-by-forcing-mistakes.html' title='Force breakthrough by forcing mistakes'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-1576191451889663889</id><published>2010-09-24T05:58:00.001-07:00</published><updated>2010-09-24T05:58:13.030-07:00</updated><title type='text'>Olijfolie</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;p&gt;Het is in Nederland niet makkelijk om goede olijfolie te vinden. Als je de spullen van de supermarkt gewend bent, weet dan dat er de gelegenheid is om een ster te winnen simpelweg door het gebruik van betere olie. In deze blog ben ik op zoek naar een goede, betaalbare olie en waarom de beste olie die ik kon vinden niet in de winkel te koop is.&lt;/p&gt;  &lt;p&gt;Bij het produceren van olijfolie worden verschillende &lt;a href="http://en.wikipedia.org/wiki/Olive_oil_extraction"&gt;extractie methoden&lt;/a&gt; gebruikt. De belangrijkste factoren zijn de lage temperatuur (eerste koude persing) en de manier van malen waarbij zo min mogelijk de pit en schil van de olijf meegeperst moeten worden.&lt;/p&gt;  &lt;p&gt;&lt;object height="417" width="500"&gt;&lt;param name="movie" value="http://www.youtube.com/v/PBX2Uv0HLqY&amp;hl=en&amp;fs=1" /&gt;&lt;/param&gt;&lt;param name="wmode" value="window" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/PBX2Uv0HLqY&amp;hl=en&amp;fs=1" allowfullscreen="true" type="application/x-shockwave-flash" allowscriptaccess="always" wmode="window" height="417" width="500"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;  &lt;p&gt;Deze beide criteria zijn in directe tegenspraak met de kwantitatieve grenzen die het winstgevend produceren van olie in hun greep houden. Immers: hoe meer olie per olijf, hoe goedkoper de productie. Hierom worden latere persingen uitgevoerd waarbij de gemalen olijven fijner worden gemalen en worden gekookt.&lt;/p&gt;  &lt;p&gt;Op zoek naar goede olie zijn veel speciaalzaken te vinden die wel prima olie hebben, maar deze olie is duur. 20 euro per liter is de prijs die de &lt;a href="http://www.kastelli.nl/" title="Het kost wat, maar dan heb je ook prima olie"&gt;olijfoliespecialist in Culemborg&lt;/a&gt; bedingt. Ik betaal graag voor goed kwaliteit, maar als het wat minder kan (qua prijs dan) ben ik ook te vinden.&lt;/p&gt;  &lt;p&gt;Vriend Tiziano nam mij een halve liter olie van &lt;a href="http://maps.google.com/maps?f=d&amp;amp;source=s_d&amp;amp;saddr=42.301424,14.1718&amp;amp;ie=UTF8&amp;amp;t=h&amp;amp;z=16" title="Goede olie hier, wordt niet geëxporteerd"&gt;zijn ouderlijk bedrijf in Italie&lt;/a&gt; mee. Vriend Guido bracht mij een kruikje olie van het vat dat hij in Kroatie had gekocht. De olie uit Kroatie kan zich gemakkelijk meten aan de producten van Kastelli, en de olie van Tiziano is beduidend beter (smaken verschillen, maar het zegt toch iets).&lt;/p&gt;  &lt;p&gt;Even rekenen hoor&amp;hellip; Er is olie die in het land van herkomst voor 5 euro per liter (of minder) verkocht kan worden, en beter is dan de olie die je voor drie keer dat bedrag in Nederland koopt. Deze olie komt niet op de markt (in het Italiaanse geval), en al helemaal niet op de internationale markt (in beide gevallen). Voor olie van de kwaliteit waar we het over hebben betaal je in de VS rustig 50 dollar per liter, en in het noorden van Europa is 40 euro per liter ook niet vreemd.&lt;/p&gt;  &lt;p&gt;Het aanbod in het land van herkomst (Italie) is groot, maar de prijzen zijn daar zo laag dat de boeren de moeite niet nemen hun olie ter verkoop aan te bieden. De vraag in het noord-westen is groter dan het aanbod aldaar (anders zouden de prijzen niet zo hoog liggen). Het grote gat tussen de prijzen die de boeren in Italië krijgen en de prijs die in de winkels in Nederland betaald word is moeilijk te verklaren.&lt;/p&gt;  &lt;p&gt;In elk geval, ik laat de conspiracy theories aan de lezer over, maar als je op vakantie gaat naar een warm land, vergeet dan niet een beetje olie bij een boer te kopen. Wel eerst even proeven hè?&lt;/p&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://eten.posterous.com/olijfolie"&gt;Koken en Eten&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-1576191451889663889?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/1576191451889663889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=1576191451889663889' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1576191451889663889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1576191451889663889'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/09/olijfolie.html' title='Olijfolie'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-6452994993377765451</id><published>2010-08-23T01:49:00.001-07:00</published><updated>2010-08-23T01:49:42.517-07:00</updated><title type='text'>Reaction to "Why ORCL was right to sue ..."</title><content type='html'>&lt;div class='posterous_autopost'&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/reaction-to-why-orcl-was-right-to-sue"&gt;iweinfuld's posterous&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-6452994993377765451?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/6452994993377765451/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=6452994993377765451' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/6452994993377765451'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/6452994993377765451'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/08/reaction-to-orcl-was-right-to-sue.html' title='Reaction to &amp;quot;Why ORCL was right to sue ...&amp;quot;'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-2661632254352656296</id><published>2010-08-20T04:54:00.001-07:00</published><updated>2010-08-20T04:54:35.895-07:00</updated><title type='text'>Forging intelligent Teams instead of staffing Projects with intelligent people</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;div&gt;In my experience with consulting and development, project teams (both Agile and traditional) invariably face issues with availability of team members. In one (rather long and messy) talk on craftsmanship Robert Martin came up with an interesting idea that I&amp;#39;d like to explore a bit more. It might actually solve this problem if used in the right way in a large organization. The idea is simple: organize into long term teams of upto 12 people and accept work from different projects as a team.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;This is actually the way small development companies have worked for ages, and they have done quite well on it. The problem is that when projects and clients get bigger they tend to turn things upside down and instead of pushing work to teams that can handle it, they start pulling resources (eww I hate that word when applied to human beings) into the project. This process is called staffing.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;There is a problem with staffing. People are not resources. The difference between people and resources (think coal, plated steel, money) is that they change based on changes in their environment. This ability is defined by Stephen Hawking as intelligence, and I like that definition. The big upside of intelligence is that it can actually solve problems for you and that is something that typical resources cannot do. If intelligence is the stuff that allows you to come up with solutions, resources are the stuff that you consume to implement them. A profound difference here is that coming up with a solution actually increases the amount of intelligence, whereas implementing a solution always decreases the amount of resources.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;If managers pretend that people are resources and projects are black boxes that turn resources into implemented solutions they will get two things: shortage of intelligence and shortcomings in implemented solutions. The shortage of intelligence is caused by the fact that a project starts being about finding a solution and invariably more and more becomes about implementing it. The former makes you smarter (increasing intelligence) the latter dumbs you down (decreasing intelligence). If you only implement solutions you lose your ability to adapt to change, but if all you ever do is adapt to change you might go crazy. There is an optimum between the amount of change a person has to handle and the amount of time he needs to regain his footing, and this is different per person.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;This is all well and fine, but how will we get those essential team members available then? I&amp;#39;m getting to it, don&amp;#39;t worry.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;First we put a team together thinking about a certain context, not a project. Then we let them establish a healthy environment for them to adapt to and increase their intelligence. This causes team members to be available to each other by default. The we let the project managers sell the work to a team, possibly multiple teams. Each team takes on what they are comfortable with but they stick together. Now this chunk of work might be too little or they might get bored with it. Then they take on some more work, possibly from another project, but they keep together as a team.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;If a team member wants to leave this is a career move, not a ephemeral thing you can do for a couple of hours on friday if you feel like it. You can&amp;#39;t be part time on one team and part time on another. If you want to take on some work you have to convince your team, or make your career move and be gone totally. Now the question of when person X is available to person Y is extremely simple. When they&amp;#39;re in the same team they can count on each other. If they are not on the same team they might have a meeting some time. &lt;/div&gt; &lt;p /&gt;&lt;div&gt;This should up a lot of things, I&amp;#39;m looking forward to try it. If anyone already has experience with this approach on a large scale or moving a large development organization into this mode I would love to hear some war stories.&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/forging-intelligent-teams-instead-of-staffing"&gt;iweinfuld's posterous&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-2661632254352656296?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/2661632254352656296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=2661632254352656296' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2661632254352656296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2661632254352656296'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/08/forging-intelligent-teams-instead-of.html' title='Forging intelligent Teams instead of staffing Projects with intelligent people'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-5026583555481909449</id><published>2010-07-27T11:41:00.001-07:00</published><updated>2010-07-27T11:41:20.651-07:00</updated><title type='text'>The Copy, then Rename pattern for file based integration</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;div&gt;This is a blog for those unlucky many of you that, like me, had to solve the file integration problem. Two processes are integrating over a directory, one writes (W), one reads (R). Now the reader picks up a file while the writer is still writing to it. BOOM, R caughs and dies. Sounds familiar? Then read on.&lt;/div&gt; &lt;p /&gt;I know I promised a blog on a deadline free utopia, but while I&amp;#39;m chewing over that one I need to jot down this thought. That&amp;#39;s what blogs are for right to capture the excess of an overflowing mind? &lt;p /&gt;&lt;div&gt;So back to R and W that can&amp;#39;t seem to get their processes synced. How do you prevent R reading that file that W is still writing? Locking will work, but it&amp;#39;s clunky and tricky. Looking at the timestamp &lt;i&gt;might &lt;/i&gt;work in most of the cases, but it is not &lt;i&gt;guaranteed&lt;/i&gt; to work under high load. Can you say &lt;a href="http://www.wordspy.com/words/heisenbug.asp"&gt;heisenbug&lt;/a&gt;? So, what can we do.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;Well in fact the solution is too simple to spend more than a few sentences on. It is old, battered and scarred, and it will be around for a while in the future. Just &lt;b&gt;Copy&lt;/b&gt; the file to a temporary name and &lt;b&gt;then Rename&lt;/b&gt; it to its final destination. Maybe I&amp;#39;ll include an image later, but you should get the point, right?&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/the-copy-then-rename-pattern-for-file-based-i"&gt;iweinfuld's posterous&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-5026583555481909449?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/5026583555481909449/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=5026583555481909449' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/5026583555481909449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/5026583555481909449'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/07/copy-then-rename-pattern-for-file-based.html' title='The Copy, then Rename pattern for file based integration'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-3280448635925877173</id><published>2010-07-19T08:12:00.001-07:00</published><updated>2010-07-19T08:12:23.127-07:00</updated><title type='text'>BBQ experiment: Grilled pineapple</title><content type='html'>&lt;div class='posterous_autopost'&gt;I'm having a barbecue with some Xebia colleagues next Tuesday. When I have a couple of guests over for the first time, I always like to play it safe a little bit, but the following two experiments just seem too easy, so I'll take the risk:&lt;p /&gt;&lt;div&gt;&lt;b&gt;Grilled Pineapple (adapted from Ananas al Forno):&lt;/b&gt;&lt;/div&gt;&lt;div&gt;For the original recipe look at this old&amp;nbsp;&lt;a href="http://italiankitchensecrets.blogspot.com/2009/07/baked-pineapple-ananas-al-forno.html"&gt;blog&lt;/a&gt;. I don't see a reason why it wouldn't work on the barbecue, and potentially improve the flavor given the right type of smoke. I'm thinking sage should work.&amp;nbsp;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;b&gt;Marinaded sweet potato&lt;/b&gt;&lt;/div&gt;&lt;div&gt;I have no clue yet how I'm going to pull it off, but I've made marinaded carrot shaslic's before and that worked out pretty well, so I'm guessing that it's &amp;quot;just&amp;quot; a matter of getting them done just right and finding the proper marinade for them.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;I'll update this post with the story of success or as it may happen disaster after Thursday, if you have any tips, warnings or other first hand accounts please help me out before I make a fool of myself.&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://eten.posterous.com/bbq-experiment-grilled-pineapple"&gt;Koken en Eten&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-3280448635925877173?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/3280448635925877173/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=3280448635925877173' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3280448635925877173'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3280448635925877173'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/07/bbq-experiment-grilled-pineapple.html' title='BBQ experiment: Grilled pineapple'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-1461319794624343183</id><published>2010-06-20T00:55:00.001-07:00</published><updated>2010-06-20T00:55:10.050-07:00</updated><title type='text'>Please stop moving deadlines</title><content type='html'>&lt;div class='posterous_autopost'&gt;I&amp;#39;ve been struggling with deadlines for a long time, and I&amp;#39;ve finally discovered the pattern that makes my struggle most painful. They move all the time. A moving target is harder to hit than a stationary target, so my theory is that the more deadlines move the more futile planning becomes. The good thing about time is that it (usually) only moves in one direction, but man has invented budgets to compensate for this glaring lack of complexity. &lt;p /&gt;&lt;div&gt;So what can we do? Well just never, ever move a deadline. I will go into detail some later post on how to avoid deadlines altogether, but for now let&amp;#39;s just consider what happens if you make the deadline stationary.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;&lt;b&gt;When you refuse to move the deadline the thing will not be DONE.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;This is not a problem. Nothing is ever done. Done is an invention by people who like tickboxes. When the deadline comes you just do what you planned to do at that deadline, or you conclude that you have failed. Failure is good. Failure is the only true done. If you have failed you are free to go do something else, probably something that you have found the inspiration to do when you were dragging around Doomed To Fail project X. A deadline that can&amp;#39;t be moved helps you to fail early and this will save time and money.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;&lt;b&gt;When you refuse to move the deadline the thing will not be as good as it can be.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;This is a misleading statement. If you&amp;#39;re building a &lt;a href="http://www.csmonitor.com/Money/new-economy/2010/0309/Runaway-Prius-Toyota-s-sudden-acceleration-woes-are-mounting"&gt;cruise control driver&lt;/a&gt;, &amp;quot;as good as it can be&amp;quot; is a well defined concept, but most of us aren&amp;#39;t building those kind of applications. What we&amp;#39;re building is usually the implementation of some idea somebody dreamed up with very limited input. It might be a very good idea, but it&amp;#39;s not well defined. In fact it&amp;#39;s our job to define it based on small hints the product owner is giving us. This makes &amp;quot;as good as it can be&amp;quot; a moving target. The longer we wait to deliver, the further ahead the dream of the business will get ahead of our actual implementation. And the bigger the disappointment when we finally do deliver what we have.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;&lt;b&gt;But just look at what we have now! We can&amp;#39;t deliver like this, right?&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Maybe you&amp;#39;re right - you&amp;#39;re probably not though. Delivering is easy and delivering something that sorta works is much better than delivering nothing at all. You don&amp;#39;t know if the business can break even with the thing you consider crap before someone tries. It is your obligation to &lt;a href="http://www.threeriversinstitute.org/blog/?p=488"&gt;try this as soon as possible&lt;/a&gt;. Cheating your customer into thinking he&amp;#39;s going to get rich is not professional.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;Much more important though: the longer you wait, the more you&amp;#39;re going to think you&amp;#39;re not ready. Dreams go faster than reality and by definition you will never catch up. By delivering whatever you have on the deadline and not moving it you&amp;#39;re delivering reality to the dreamers. The earlier you do this the more they will keep liking you.&lt;/div&gt; &lt;p /&gt;&lt;div&gt;&lt;b&gt;Ok, no more moving deadlines. But what happens after the deadline?&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Well, its simple. After the deadline people will invariably think it can be done better. If you deliver your ideas of how to do things better with the unfinished product, you might get a chance to fix the things you wanted to fix before delivering. The good news is that you will get that chance based on realistic expectations. And if you don&amp;#39;t get that chance you&amp;#39;re free to do something else, which might not be a bad thing at all.&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/please-stop-moving-deadlines"&gt;iweinfuld's posterous&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-1461319794624343183?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/1461319794624343183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=1461319794624343183' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1461319794624343183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1461319794624343183'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/06/please-stop-moving-deadlines.html' title='Please stop moving deadlines'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-1513185450042705185</id><published>2010-06-18T11:02:00.001-07:00</published><updated>2010-06-18T11:02:17.505-07:00</updated><title type='text'>Stir fried spicy spinach</title><content type='html'>&lt;div class='posterous_autopost'&gt;There&amp;#39;s nothing original about stir fried spinach with a dash of other flavors, but this combination was pleasant enough to mention anyway. &lt;p /&gt;&lt;div&gt;Per person:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;200g spinach&lt;/li&gt; &lt;li&gt;2 cloves garlic&lt;/li&gt; &lt;li&gt;2 thai chilies (a normal chili pepper should work fine too)&lt;/li&gt;&lt;li&gt;juice of half a lemon&lt;/li&gt;&lt;li&gt;1 tbsp grenadine concentrate (&lt;span style="font-family: arial, sans-serif; line-height: 15px;"&gt;Ayurveda)&lt;/span&gt;&lt;/li&gt; &lt;li&gt;arachide oil&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;Heat the oil over medium heat, add the ginger  in fine slices so it can get acquainted with the oil. When the ginger is getting soft add the garlic (bashed and chopped) and chilly, also finely sliced. After a minute or so, add the spinach and increase the heat. Stir until the spinach is done and add the grenadine and stir again. Finally turn of the heat and add the lemon. The taste is quite funky, but definitely worth the 10m that it takes to make.&lt;/div&gt; &lt;/div&gt;  &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://eten.posterous.com/stir-fried-spicy-spinach"&gt;Koken en Eten&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-1513185450042705185?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/1513185450042705185/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=1513185450042705185' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1513185450042705185'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1513185450042705185'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/06/stir-fried-spicy-spinach.html' title='Stir fried spicy spinach'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-3689560979914558332</id><published>2010-06-14T10:34:00.001-07:00</published><updated>2010-06-14T10:34:49.164-07:00</updated><title type='text'>Untitled</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;p&gt;I made this for lunch yesterday and it was even better than I expected:&lt;/p&gt;  &lt;ul&gt;  &lt;li&gt;3 eggs&lt;/li&gt;  &lt;li&gt;handful of coriander leaves&lt;/li&gt;  &lt;li&gt;two hands full of mushrooms&lt;/li&gt;  &lt;li&gt;juice of half a lime&lt;/li&gt;  &lt;li&gt;2 tbsp of skimmed milk&lt;/li&gt;  &lt;li&gt;1 tbsp sesame oil&lt;/li&gt;  &lt;li&gt;1 tbsp sweet soya sauce&lt;/li&gt;  &lt;li&gt;1 tsp thai fish sauce&lt;/li&gt;  &lt;li&gt;rice oil (to fry in)&lt;/li&gt;  &lt;/ul&gt;  &lt;p&gt;Chop the coriander and whisk all ingredients together except for the rice oil and the mushrooms. Slice mushrooms. Heat up a frying pan and toss in the oil and mushrooms. Fry until the mushrooms have lost most of their liquids and give off their aroma.Reduce the heat (or take the pan off the heat for the moment). Whisk the mushrooms into the omelet mixture. Make sure the pan is clean (if you have a good pan you can just stare at it for 0.5 seconds), add some more oil if needed and gently poor the omelet mixture into the pan so that the mushrooms are spread well. Gently fry the omelet on medium heat, turn it if you feel like it. When it's golden brown and completely solid you can eat.&lt;p /&gt; (all the amounts in this recipe are wild guesses as usual, I don't believe in careful measurements when cooking)&lt;/p&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via web&lt;/a&gt;  from &lt;a href="http://eten.posterous.com/20334511"&gt;Koken en Eten&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-3689560979914558332?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/3689560979914558332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=3689560979914558332' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3689560979914558332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3689560979914558332'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/06/untitled.html' title='Untitled'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-4726152153532172823</id><published>2010-06-14T02:15:00.001-07:00</published><updated>2010-06-14T02:15:50.797-07:00</updated><title type='text'>Note to self: how to sparsely check out a git repository</title><content type='html'>&lt;div class='posterous_autopost'&gt;Today I discussed with&amp;nbsp;&lt;a href="http://twitter.com/david_syer"&gt;Dave Syer&lt;/a&gt;&amp;nbsp;about some improvements in&amp;nbsp;&lt;a href="http://www.springsource.org/spring-integration"&gt;Spring Integration&lt;/a&gt;, which I had&amp;nbsp;&lt;a href="http://github.com/iwein/Spring-Integration-Sandbox/"&gt;sandboxed&lt;/a&gt;&amp;nbsp;in my messy github repository. A sparse checkout would be convenient, but we both didn't know how to do it. I even thought git didn't support it,&amp;nbsp;&lt;a href="http://twitter.com/iweinfuld/status/16131733994"&gt;but boy was I wrong&lt;/a&gt;!&lt;p /&gt;&lt;div&gt;&lt;div&gt;&lt;span style="font-size: 12px;"&gt;iwein:si-sandbox$ git init&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12px;"&gt;Initialized empty Git repository in /tmp/si-sandbox/.git/&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12px;"&gt;(master) iwein:si-sandbox$ git config core.sparsecheckout true&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12px;"&gt;(master) iwein:si-sandbox$ echo message-store/ &amp;gt;&amp;gt; .git/info/sparse-checkout&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12px;"&gt;(master) iwein:si-sandbox$ git remote add origin &lt;a&gt;git://github.com/iwein/Spring-Integration-Sandbox.git&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size: 12px;"&gt;(master) iwein:si-sandbox$ git pull origin master&lt;/span&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;The important thing to remember is that this also works with git-clone. Your index will still have everything, just your checkout (working copy generated from the index) will not. This is a big difference with&amp;nbsp;&lt;a href="http://svnbook.red-bean.com/en/1.5/svn.advanced.sparsedirs.html"&gt;svn sparse directories&lt;/a&gt;, and as usual it's an improvement.&lt;/div&gt;&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/note-to-self-how-to-sparsely-check-out-a-git"&gt;iweinfuld's posterous&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-4726152153532172823?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/4726152153532172823/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=4726152153532172823' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/4726152153532172823'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/4726152153532172823'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/06/note-to-self-how-to-sparsely-check-out.html' title='Note to self: how to sparsely check out a git repository'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-6734817063064981081</id><published>2010-06-13T05:03:00.001-07:00</published><updated>2010-06-13T05:03:05.170-07:00</updated><title type='text'>Using negative feedback to prevent disaster in Software Development</title><content type='html'>&lt;div class='posterous_autopost'&gt;Invariably we are taught that when working with people we should give them plenty of positive feedback whenever they do something right and be very careful with negative feedback. I've never completely bought into this hugging hippie attitude, but it seems there is a good point there: if we're all nice to each other and keep a positive spirit, we get more done right? The problem with this approach is that it doesn't take into account that it might be important to not get something done. Some ideas are just terrible and they should be killed off as soon as possible.&lt;p /&gt;  When I had the idea for this blog I thought it would fit on twitter. &amp;quot;&lt;span class="status-body"&gt;&lt;span class="status-content"&gt;&lt;span class="entry-content"&gt;Positive feedback induces brilliance, negative feedback prevents disaster. The latter is sadly undervalued.&amp;quot; &lt;a href="http://twitter.com/iweinfuld/status/14759550338"&gt;i twote&lt;/a&gt;. It seems this could use a few backing arguments and today I've made time to provide them.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; I will explain why negative feedback is important and how you can apply it to your advantage.&lt;p /&gt; &lt;b&gt;What's the problem with positive feedback?&lt;br /&gt; &lt;/b&gt;Positive feedback induces brilliance. Like the brilliant glow of a nuclear meltdown is caused by positive feedback. If you're doing something absolutely great, positive feedback will cause you to do more of it and it will cause others to try and emulate your behavior. Brilliant right? But what if you're doing something that is ever so slightly off target? Will positive feedback make you augment your course? Will it make others slightly vary your behavior before emulating it? I don't think so. You need negative feedback to change.&lt;p /&gt;  I have a background in physics and some electronics and signal analysis is part of that background. In electronics positive feedback doesn't have the credits that it has in social studies. It is viewed as a destructive force that will ruin your signal, make your appliance useless, or even destroy things. Let's look at the example of a feedback loop in it's most generic form:&lt;p /&gt;&lt;p /&gt; &lt;p&gt;       &lt;div style='padding: 5px 5px 10px 5px; margin-top: 5px; border: 1px solid #ddd; background-color: #fff;line-height: 16px;'&gt;       &lt;div style="float: left; margin-right: 5px; overflow: visible;"&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/Uno9lWFP4teeSh7V5BxN5p7gbVKFFo0DSN1pGZiuR7A76c9RcS0gkm0fqs5h/PastedGraphic-1.pdf' style='color: #bc7134;'&gt;&lt;img src='http://posterous.com/images/filetypes/pdf.png' style='border: none;'/&gt;&lt;/a&gt;&lt;/div&gt;       &lt;div style="font-size: 10px; color: #424037;line-height: 16px;"&gt;Download now or &lt;a href='http://iweinfuld.posterous.com/using-negative-feedback-to-prevent-disaster-i' style='color: #bc7134;'&gt;preview on posterous&lt;/a&gt;&lt;/div&gt;       &lt;b&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/Uno9lWFP4teeSh7V5BxN5p7gbVKFFo0DSN1pGZiuR7A76c9RcS0gkm0fqs5h/PastedGraphic-1.pdf' style='color: #bc7134;'&gt;PastedGraphic-1.pdf&lt;/a&gt;&lt;/b&gt; &lt;span style="font-size: 10px; color: #424037;"&gt;(18 KB)&lt;/span&gt;       &lt;br style="clear: both;"/&gt;&lt;/div&gt;      &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;p /&gt;  In the diagram you see input being processed by a system G the output of G is connected to its input via a feedback loop. If the feedback is negative or zero, the output will be strictly related to the input. If the input drops, the output goes to zero. If the feedback is positive two things can happen: first, if the feedback is less than the input, the output will eventually go to zero, but it takes more than one loop. In audio this is called an echo. It's not dangerous, but it can pollute the output if the echo is of a sound that you didn't want to hear. If the feedback signal is stronger than the input, when the input drops the output will &lt;b&gt;continue to increase&lt;/b&gt;. In audio this is called a feedback loop, the typical symptom is a high frequency tone that gets louder and louder until either the speaker gives or the amplifier can't go any louder. This is not considered a good thing generally.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;If we apply this model to human interaction, it still works. Let's say the input is an idea by developer Joe, G is the team. Let's say the idea is to improve quality by adding more test cases. Let's say the idea pays off the first loop and everybody is very happy. This causes some serious positive feedback. The feedback will say: "More testing is good". And more resources will be invested in testing. Depending on the positive attitude of the team this will lead to more and more resources being spent on creating tests, until there are no more tests to write or the team is out of resources. As much as I like tests, that's crazy. So developer Bill will come with the great idea to spend less time on testing. The first loop this will get positive feedback because the team gets stuff done again and the tests are in place to keep them safe. Two loops later we're in the hole again, quality is crap, coverage is abominable, we're stuck. Rinse and repeat. Does this really happen? You bet!&lt;/div&gt;&lt;p /&gt;&lt;div&gt;There is a dangerous psychological phenomenon that is entirely caused by positive feedback in groups, dubbed&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Groupthink"&gt;Group Think&lt;/a&gt;&lt;/div&gt;&lt;p /&gt;&lt;div&gt;The reason that people fall into this trap in my opinion is that they have the instincts to give positive feedback and act on it. Also our education system is based on it because&amp;nbsp;&lt;a href="http://www.childrenlights.com/Articles/article_empowering_children_affirmations.htm"&gt;it works well on small children&lt;/a&gt;. But in fact getting only positive feedback makes you lazy and stupid. What can we do? Simple: introduce negative feedback.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;&lt;b&gt;I thought negative feedback was bad?&lt;/b&gt;&lt;/div&gt;&lt;div&gt;If negative feedback means bashing then yes, it's bad. If negative feedback means using force, it's bad. If negative feedback is used to block others, it's bad. But it doesn't have to be that way. In the case were Joe suggested testing the first iteration good things happened, but then it spun out of control.&lt;/div&gt;&lt;p /&gt;&lt;p&gt;       &lt;div style='padding: 5px 5px 10px 5px; margin-top: 5px; border: 1px solid #ddd; background-color: #fff;line-height: 16px;'&gt;       &lt;div style="float: left; margin-right: 5px; overflow: visible;"&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/nWyVZv66aO6bGrSAB7DhtHhZ0X8dc0Ob0xpm1wKjjWQjZQ712BUXwmK93pwz/PastedGraphic-5.pdf' style='color: #bc7134;'&gt;&lt;img src='http://posterous.com/images/filetypes/pdf.png' style='border: none;'/&gt;&lt;/a&gt;&lt;/div&gt;       &lt;div style="font-size: 10px; color: #424037;line-height: 16px;"&gt;Download now or &lt;a href='http://iweinfuld.posterous.com/using-negative-feedback-to-prevent-disaster-i' style='color: #bc7134;'&gt;preview on posterous&lt;/a&gt;&lt;/div&gt;       &lt;b&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/nWyVZv66aO6bGrSAB7DhtHhZ0X8dc0Ob0xpm1wKjjWQjZQ712BUXwmK93pwz/PastedGraphic-5.pdf' style='color: #bc7134;'&gt;PastedGraphic-5.pdf&lt;/a&gt;&lt;/b&gt; &lt;span style="font-size: 10px; color: #424037;"&gt;(18 KB)&lt;/span&gt;       &lt;br style="clear: both;"/&gt;&lt;/div&gt;      &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p /&gt;&lt;div&gt;The team lost track of the goal: working software and started focussing on some symptoms like test coverage.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;In the next image the green arrow are the actions the team is taking, the red arrows are the negative feedback that is applied to reach their goal instead of overshooting it.&amp;nbsp;&lt;/div&gt;&lt;p /&gt;&lt;p /&gt;&lt;p&gt;       &lt;div style='padding: 5px 5px 10px 5px; margin-top: 5px; border: 1px solid #ddd; background-color: #fff;line-height: 16px;'&gt;       &lt;div style="float: left; margin-right: 5px; overflow: visible;"&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/mIDxM52DuCA9RuQyyZq8xOF7Bv2akFgA0MHGLvzIU3YRZRMIVHB1oQHSEP2h/PastedGraphic-4.pdf' style='color: #bc7134;'&gt;&lt;img src='http://posterous.com/images/filetypes/pdf.png' style='border: none;'/&gt;&lt;/a&gt;&lt;/div&gt;       &lt;div style="font-size: 10px; color: #424037;line-height: 16px;"&gt;Download now or &lt;a href='http://iweinfuld.posterous.com/using-negative-feedback-to-prevent-disaster-i' style='color: #bc7134;'&gt;preview on posterous&lt;/a&gt;&lt;/div&gt;       &lt;b&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/mIDxM52DuCA9RuQyyZq8xOF7Bv2akFgA0MHGLvzIU3YRZRMIVHB1oQHSEP2h/PastedGraphic-4.pdf' style='color: #bc7134;'&gt;PastedGraphic-4.pdf&lt;/a&gt;&lt;/b&gt; &lt;span style="font-size: 10px; color: #424037;"&gt;(19 KB)&lt;/span&gt;       &lt;br style="clear: both;"/&gt;&lt;/div&gt;      &lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p /&gt;&lt;p /&gt;&lt;div&gt;The important thing is not to stop the team from doing what it's doing, just to stop it from doing it too much. Make the team do it better instead of more. In some cases a really terrible idea comes up and no time should be wasted on it. In those cases people usually have no problem killing off the idea. The problem arises when a good idea comes up but the implementation is not completely right. It's only human to want to move forward when you're going strong and that makes it very easy to overshoot the goal entirely. The trick is to gradually apply more corrective negative feedback once the team gets closer to a goal.&lt;/div&gt;&lt;p /&gt;&lt;div&gt;Thinking about decision processes using this metaphor works for me. I hope you find it useful too.&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/using-negative-feedback-to-prevent-disaster-i"&gt;iweinfuld's posterous&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-6734817063064981081?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/6734817063064981081/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=6734817063064981081' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/6734817063064981081'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/6734817063064981081'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/06/using-negative-feedback-to-prevent.html' title='Using negative feedback to prevent disaster in Software Development'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-6130093876952387733</id><published>2010-05-27T00:02:00.001-07:00</published><updated>2010-05-27T00:02:14.116-07:00</updated><title type='text'>How to build Spring Integration from the sources</title><content type='html'>&lt;div class='posterous_autopost'&gt;This is a guide on setting up your machine for Spring Integration development. I&amp;#39;ve got questions about this many times so I thought it was time I put the answer where Google could see it. Let&amp;#39;s say you want to create a patch for a bug in Spring Integration, or you want to run a test case to see how some component works. First you need to take that annoying hurdle of getting the project to build locally. You&amp;#39;re going in the right direction, but you&amp;#39;ve missed some turns. If that sounds familiar, read on!&lt;p /&gt; Before you go into the IDE part, make sure you have got the basics right. I can&amp;#39;t stress this enough, if you can&amp;#39;t get it to work from the command line you&amp;#39;re doomed, no tool can help you. So the 5 first steps don&amp;#39;t involve an IDE.&lt;p /&gt; &lt;b&gt;Prepare your system for Spring Integration development&lt;/b&gt;&lt;br /&gt;0. Forget about your IDE and open up a terminal (on Windows there are &lt;a href="https://help.ubuntu.com/community/GraphicalInstall"&gt;some extra steps&lt;/a&gt;).&lt;p /&gt; 1. make sure you have a command line svn client (there are many installation procedures) the end result should be:&lt;br /&gt;&lt;span style="font-family: courier new,monospace;"&gt;(master) iwein:si$ svn --version&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt; &lt;span style="font-family: courier new,monospace;"&gt;svn, version 1.6.11 (r934486)&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt;&lt;span style="font-family: courier new,monospace;"&gt;   compiled Apr 19 2010, 23:04:06&lt;/span&gt;&lt;br /&gt; Any version later than 1.6 will do I think.&lt;p /&gt;2. make sure you have the right version of Java:&lt;br /&gt;&lt;span style="font-family: courier new,monospace;"&gt;(master) iwein:si$ java -version&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt; &lt;span style="font-family: courier new,monospace;"&gt;java version &amp;quot;1.6.0_15&amp;quot;&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt;&lt;span style="font-family: courier new,monospace;"&gt;Java(TM) SE Runtime Environment (build 1.6.0_15-b03-219)&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt; &lt;span style="font-family: courier new,monospace;"&gt;Java HotSpot(TM) 64-Bit Server VM (build 14.1-b02-90, mixed mode)&lt;/span&gt;&lt;p /&gt;This might be a bit confusing and I want to avoid the details, but you need to remember that Spring and also Spring Integration are compatible with Java 1.5, but the &lt;i&gt;build&lt;/i&gt; is not necessarily. 1.6 is fine.&lt;p /&gt; 3. make sure you have the right version of Maven:&lt;br /&gt;&lt;span style="font-family: courier new,monospace;"&gt;(master) iwein:elmar-trunk$ mvn -version&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt;&lt;span style="font-family: courier new,monospace;"&gt;Maven version: 2.0.9&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt; &lt;span style="font-family: courier new,monospace;"&gt;Java version: 1.6.0_15&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt;&lt;span style="font-family: courier new,monospace;"&gt;OS name: &amp;quot;mac os x&amp;quot; version: &amp;quot;10.6&amp;quot; arch: &amp;quot;x86_64&amp;quot; Family: &amp;quot;mac&amp;quot;&lt;/span&gt;&lt;p /&gt; Any 2.0.x version will do (except the ones with bugs :) ).&lt;p /&gt;4. check out the trunk:&lt;br /&gt;&lt;span style="font-family: courier new,monospace;"&gt;iwein:si-temp$ svn co &lt;a href="https://src.springsource.org/svn/spring-integration/trunk/"&gt;https://src.springsource.org/svn/spring-integration/trunk/&lt;/a&gt;&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt; This will give you a lot of output, but no errors.&lt;p /&gt;5. Build the project:&lt;br /&gt;&lt;span style="font-family: courier new,monospace;"&gt;iwein:si-temp$ cd trunk/&lt;/span&gt;&lt;br style="font-family: courier new,monospace;" /&gt;&lt;span style="font-family: courier new,monospace;"&gt;iwein:trunk$ mvn clean install&lt;/span&gt;&lt;br /&gt; Again a lot of output, but no errors&lt;p /&gt;6. Import the project in your IDE&lt;br /&gt;Using the power of google you can find guides for: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.jetbrains.com/idea/webhelp/importing-maven-project.html"&gt;importing a maven project in IDEA&lt;/a&gt;&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.theserverside.com/news/1363817/Introduction-to-m2eclipse"&gt;using m2eclipse&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://wiki.netbeans.org/MavenBestPractices"&gt;working with maven projects in NetBeans&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;It&amp;#39;s a matter of taste how you do it, and if these fancy IDE&amp;#39;s are not for you there is always vim. Point is that as long as you make sure everything works from the command line, the IDE support is just a convenience that you could live without (theoretically).&lt;p /&gt; &lt;b&gt;Other options&lt;/b&gt;&lt;br /&gt;If you don&amp;#39;t like Subversion, you can also use git. Make sure you have git and git-svn installed and then run:&lt;br /&gt;&lt;span style="font-family: courier new,monospace;"&gt;git svn clone&lt;/span&gt; &lt;span style="font-family: courier new,monospace;"&gt;&lt;a href="https://src.springsource.org/svn/spring-integration/trunk/"&gt;https://src.springsource.org/svn/spring-integration/trunk/&lt;/a&gt; -r HEAD&lt;/span&gt;&lt;br /&gt; If you don&amp;#39;t know Subversion yet, I&amp;#39;d recommend this option.&lt;p /&gt;If you are bored with Maven you could also check out the &lt;a href="http://github.com/hierynomus/spring-integration"&gt;Spring Integration gradle build by Jeroen van Erp&lt;/a&gt;. Using a fork makes you dependent on Jeroen for porting commits on the Subversion HEAD, or your own merge skills, but the coolness of gradle might very well be worth it.&lt;p /&gt; Let me know if you run into trouble or if you think I missed a step. Happy hacking! &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/how-to-build-spring-integration-from-the-sour"&gt;iweinfuld's posterous&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-6130093876952387733?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/6130093876952387733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=6130093876952387733' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/6130093876952387733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/6130093876952387733'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/05/how-to-build-spring-integration-from.html' title='How to build Spring Integration from the sources'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-7280757019050970594</id><published>2010-05-16T05:23:00.003-07:00</published><updated>2010-05-16T05:23:17.686-07:00</updated><title type='text'>Simplifying Spring Integration testing</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;p&gt;It seems like last week that I would happily write things like "&lt;span style="font-family: georgia,serif;"&gt;public abstract class BaseMyCompanyTest extends AbstractTransactionalDatasourceSpringContextTests {&lt;/span&gt;" and think I was the man. It seems like yesterday that Spring 2.5 came along and made things a lot easier with &lt;span style="font-family: georgia,serif;"&gt;@ContextConfiguration&lt;/span&gt;. But now I find myself grinding against the boilerplate again.&lt;p /&gt; Before I start tearing it down let me first tell you that I highly respect the work by &lt;a href="http://sambrannen.com/"&gt;Sam Brannen&lt;/a&gt; and that I have gotten very good mileage out it for over two years now. There is always room for improvement and that is the aim of the following experiment.&lt;p /&gt; The TestContext framework that comes with Spring might be very useful, it is also quite complex. You can only use it with a custom testrunner and and you need to pass the location of the configurations to be loaded in a class level annotation. This means it is non trivial and asymmetric to load multiple contexts in a single test. Also the incantations you have to put on the class are not exactly concise (although they are much better than the &lt;span style="font-family: georgia,serif;"&gt;AbstractTooFreakinLongClassNames&lt;/span&gt; options of old).&lt;p /&gt; &lt;a href="http://www.junit.org/node/580"&gt;Since JUnit 4.7 there is &lt;span style="font-family: georgia,serif;"&gt;@Rule&lt;/span&gt;&lt;/a&gt;. And you can do some &lt;a href="http://blog.xebia.com/2009/10/23/junit-4-7-rules/"&gt;pretty&lt;/a&gt; &lt;a href="http://blog.xebia.com/2010/03/30/making-screenshots-from-selenium-with-junit-rules/"&gt;cool&lt;/a&gt; stuff with it. When &lt;a href="http://iweinfuld.posterous.com/combining-temporaryfolder-rule-with-spring-3"&gt;combining it with Spring&lt;/a&gt; though I wasn't impressed. I felt that Spring Test was making it hard to use the power of Rules. This is ironic, since it is just this JUnit feature that would make Spring Test a lot better.&lt;/p&gt;  &lt;div&gt; &lt;br /&gt;How cool would it be if you could write:&lt;br /&gt;&lt;div class="data syntax type-java"&gt;  &lt;table cellspacing="0" cellpadding="0"&gt; &lt;tr&gt; &lt;td&gt; &lt;pre class="line_numbers"&gt;&lt;span rel="#L1" id="LID1"&gt;1&lt;/span&gt; &lt;span rel="#L2" id="LID2"&gt;2&lt;/span&gt; &lt;span rel="#L3" id="LID3"&gt;3&lt;/span&gt; &lt;span rel="#L4" id="LID4"&gt;4&lt;/span&gt; &lt;span rel="#L5" id="LID5"&gt;5&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;&amp;nbsp;&amp;nbsp;&lt;span class="nd"&gt;@Rule&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;TemporarySpringContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;TemporarySpringContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;context.xml&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="nd"&gt;@Autowired&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;ApplicationContext&lt;/span&gt; &lt;span class="n"&gt;thisShouldBeWired&lt;/span&gt;&lt;span class="o"&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;br /&gt;And it would just work?&lt;p /&gt;Gues what, I've got a green test that says it does! It only took me 50 lines of code, which you can &lt;a href="http://github.com/iwein/Spring-Integration-Sandbox/tree/a3fd31ff93cd50809a127543f7418674a77817c2/spring-test"&gt;find&lt;/a&gt; in &lt;a href="http://github.com/iwein/Spring-Integration-Sandbox"&gt;my spring sandbox on github&lt;/a&gt;. &lt;p /&gt; The important class is this the &lt;span style="font-family: georgia,serif;"&gt;TemporarySpringContext&lt;/span&gt; (which I might give a better name soon):&lt;br /&gt;&lt;div class="data syntax type-java"&gt;  &lt;table cellspacing="0" cellpadding="0"&gt; &lt;tr&gt; &lt;td&gt; &lt;pre class="line_numbers"&gt;&lt;span rel="#L1" id="LID1"&gt;1&lt;/span&gt; &lt;span rel="#L2" id="LID2"&gt;2&lt;/span&gt; &lt;span rel="#L3" id="LID3"&gt;3&lt;/span&gt; &lt;span rel="#L4" id="LID4"&gt;4&lt;/span&gt; &lt;span rel="#L5" id="LID5"&gt;5&lt;/span&gt; &lt;span rel="#L6" id="LID6"&gt;6&lt;/span&gt; &lt;span rel="#L7" id="LID7"&gt;7&lt;/span&gt; &lt;span rel="#L8" id="LID8"&gt;8&lt;/span&gt; &lt;span rel="#L9" id="LID9"&gt;9&lt;/span&gt; &lt;span rel="#L10" id="LID10"&gt;10&lt;/span&gt; &lt;span rel="#L11" id="LID11"&gt;11&lt;/span&gt; &lt;span rel="#L12" id="LID12"&gt;12&lt;/span&gt; &lt;span rel="#L13" id="LID13"&gt;13&lt;/span&gt; &lt;span rel="#L14" id="LID14"&gt;14&lt;/span&gt; &lt;span rel="#L15" id="LID15"&gt;15&lt;/span&gt; &lt;span rel="#L16" id="LID16"&gt;16&lt;/span&gt; &lt;span rel="#L17" id="LID17"&gt;17&lt;/span&gt; &lt;span rel="#L18" id="LID18"&gt;18&lt;/span&gt; &lt;span rel="#L19" id="LID19"&gt;19&lt;/span&gt; &lt;span rel="#L20" id="LID20"&gt;20&lt;/span&gt; &lt;span rel="#L21" id="LID21"&gt;21&lt;/span&gt; &lt;span rel="#L22" id="LID22"&gt;22&lt;/span&gt; &lt;span rel="#L23" id="LID23"&gt;23&lt;/span&gt; &lt;span rel="#L24" id="LID24"&gt;24&lt;/span&gt; &lt;span rel="#L25" id="LID25"&gt;25&lt;/span&gt; &lt;span rel="#L26" id="LID26"&gt;26&lt;/span&gt; &lt;span rel="#L27" id="LID27"&gt;27&lt;/span&gt; &lt;span rel="#L28" id="LID28"&gt;28&lt;/span&gt; &lt;span rel="#L29" id="LID29"&gt;29&lt;/span&gt; &lt;span rel="#L30" id="LID30"&gt;30&lt;/span&gt; &lt;span rel="#L31" id="LID31"&gt;31&lt;/span&gt; &lt;span rel="#L32" id="LID32"&gt;32&lt;/span&gt; &lt;span rel="#L33" id="LID33"&gt;33&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TemporarySpringContext&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;TestWatchman&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="cm"&gt;/**&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;&lt;span class="cm"&gt;   * Cache of Spring application contexts. This needs to be static, as tests&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;&lt;span class="cm"&gt;   * are typically destroyed and recreated between running individual test methods.&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;&lt;span class="cm"&gt;   */&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC6"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;ContextCache&lt;/span&gt; &lt;span class="n"&gt;contextCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ContextCache&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC8"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="n"&gt;ConfigurableApplicationContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC9"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;contextLocations&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC10"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC11"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;TemporarySpringContext&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;contextLocations&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC12"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contextLocations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contextLocations&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC13"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC14"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;contextCache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;contextForLocations&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contextLocations&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC15"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC16"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;RuntimeException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC17"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC18"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="o"&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;&amp;nbsp;&amp;nbsp;&lt;span class="nd"&gt;@Override&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC21"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Statement&lt;/span&gt; &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Statement&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FrameworkMethod&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&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;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAutowireCapableBeanFactory&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;autowireBean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC23"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;apply&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC24"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC25"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC26"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ConfigurableApplicationContext&lt;/span&gt; &lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC27"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC28"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC29"&gt;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div class="line" id="LC30"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;dirtyContext&lt;/span&gt;&lt;span class="o"&gt;(){&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC31"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="n"&gt;contextCache&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;markDirty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contextLocations&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC32"&gt;&amp;nbsp;&amp;nbsp;&lt;span class="o"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC33"&gt;&lt;span class="o"&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;/div&gt;  &lt;div&gt; &lt;br /&gt;Because it extends &lt;span style="font-family: georgia,serif;"&gt;TestWatchman&lt;/span&gt; you can hook into al the phases of your test by simply overriding a method. Because it is just a &lt;span style="font-family: georgia,serif;"&gt;MethodRule&lt;/span&gt; field you can add different contexts to your test class. There is plenty of room to polish this, but it has more potential than the &lt;span style="font-family: georgia,serif;"&gt;SpringJUnit4ClassRunner&lt;/span&gt; I think.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;Since most of the heavy lifting is still being done by Spring Test behind the scenes by the way. The &lt;span style="font-family: georgia,serif;"&gt;ContextCache&lt;/span&gt; is the only complex part (yet) but I have some tricks to pull to make &lt;span style="font-family: georgia,serif;"&gt;@Transactional&lt;/span&gt; and such work. If you fix it before me I owe you a beer :)&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/simplifying-spring-integration-testing"&gt;iweinfuld's posterous&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-7280757019050970594?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/7280757019050970594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=7280757019050970594' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/7280757019050970594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/7280757019050970594'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/05/simplifying-spring-integration-testing.html' title='Simplifying Spring Integration testing'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-9199285734508215818</id><published>2010-05-16T05:23:00.001-07:00</published><updated>2010-05-16T05:23:03.587-07:00</updated><title type='text'>Excuse me, your fly is open</title><content type='html'>&lt;div class='posterous_autopost'&gt;&lt;p&gt;After I showed a colleague a trick in my IDE he told me to write a blog post about it. I told him to write it himself. This all happened almost a year ago. The problem with this post is that it's about something that is a bit embarrassing. I'm losing my appetite for talking about it, but yet, I come across more setups that are wrong than setups that are right. This post is mostly about some settings in Eclipse (and also in IntelliJ IDEA) that are pretty moronic and that you should change asap to prevent bugs in your code. Otherwise you might be seen with an open fly and you wouldn't want that would you?&lt;/p&gt;  &lt;p /&gt;  &lt;div&gt;&lt;strong&gt;First a word on keyboard shortcuts&lt;/strong&gt;&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;First of all: learn to use your tool!  Here's a list of things that I see people wasting effort on:&lt;/div&gt;  &lt;div&gt;- click through the menu (unless you're trying to find what the keyboard shortcut is you're looking for)&lt;/div&gt;  &lt;div&gt;- declare a variable or field (use extract variable instead)&lt;/div&gt;  &lt;div&gt;- type the skeleton of a method (your IDE can do that much faster using a quick fix)&lt;/div&gt;  &lt;div&gt;- create a new type other than a test case yourself (generate everything from a test case, it's faster, trust me on this one)&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;There are many more variations on the same theme, the last point is arguable, some people are really fast if they start to hash out the model before beginning a test. My point is that it pays off to find the shortest path to a certain solution and figure out what shortcuts get you along that path fastest. The best way to train yourself to use the keyboard is to stick to the first point. There is even &lt;a href="http://www.mousefeed.com/"&gt;an eclipse plugin that can enforce keyboard usage&lt;/a&gt; (but that's a little too harsh for my taste). There are many blogs describing the keyboard shortcuts in great detail as well.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;&lt;strong&gt;Templates&lt;/strong&gt;&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;When you stop using your advanced typing skills and let the IDE do the typing for you, you will have moved on to using templates. In eclipse, if you look for templates under preferences (just type templates in the filter).&lt;/div&gt;  &lt;div&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/cuUUQvDVVGaiMjlZyZUEBRRGu3HWggn6z0dwqChf1KbxWqNDPKiWrNtF5PSa/PastedGraphic-3.png'&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iweinfuld/ZuPQVijTbcPwu06GFVH6EZuqTMzVivRZkDXTggzcZWulr4q0kr7qM8NuPl62/PastedGraphic-3.png.scaled.500.jpg" width="500" height="241"/&gt;&lt;/a&gt; &lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;You will find quite a few templates that are useful, some that you'll never use and the best news is that you can create your own too. I can recommend renaming the JUnit4 template to tst (instead of the default Test in eclipse) and tweaking it a bit to your coding standards, but that's not why we're here now.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;Not all these templates are sensible, and that is what I want to to fix.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;&lt;strong&gt;New method body&lt;/strong&gt;&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;A new method you can create by just trying to use the method and then asking Eclipse to create the missing method for you.&lt;/div&gt;  &lt;div&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iweinfuld/D6vhklbQv5hsXDmVG2Dy6QikwOB445RxsWqbxR5FWldVJXLIBZfViviEVYzf/PastedGraphic-1.png" width="429" height="229"/&gt; &lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;You'll end up with a method like this:&lt;/div&gt;  &lt;div&gt;&lt;div class="data syntax type-java"&gt;  &lt;table cellspacing="0" cellpadding="0"&gt; &lt;tr&gt; &lt;td&gt;  &lt;pre class="line_numbers"&gt; &lt;span rel="#L1" id="LID1"&gt;1&lt;/span&gt; &lt;span rel="#L2" id="LID2"&gt;2&lt;/span&gt; &lt;span rel="#L3" id="LID3"&gt;3&lt;/span&gt; &lt;span rel="#L4" id="LID4"&gt;4&lt;/span&gt; &lt;span rel="#L5" id="LID5"&gt;5&lt;/span&gt; &lt;span rel="#L6" id="LID6"&gt;6&lt;/span&gt; &lt;span rel="#L7" id="LID7"&gt;7&lt;/span&gt; &lt;span rel="#L8" id="LID8"&gt;8&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reverser&lt;/span&gt; &lt;span class="o"&gt;{&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="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;		&lt;span class="c1"&gt;// TODO Auto-generated method stub&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC6"&gt;	&lt;span class="o"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC8"&gt;&lt;span class="o"&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;/div&gt;  &lt;p /&gt;  &lt;div&gt;Which is pretty bad because it will allow your code to run without complaining and leave a crappy piece of comment in there. It's not the end of the world though, and you'll notice later right? You probably won't, but you don't have to, more on that in a minute. First let's make the method return a String.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;Stop, don't start modifying the method, just delete it. Eclipse will generate it correctly for you later.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;Modify the test a bit so you need a String return value and try the quick fix again.&lt;/div&gt;  &lt;div&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/eGX4tSi2qoVFp09WRTAD1elgunLOC7LHJ0UPAr6q1On2iA78F99AYYAfkvyK/PastedGraphic-2.png'&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iweinfuld/Sb6LjgGpKbGtK55wtO9fBOaXVuqVx9UZmyAu50bZpMlEwcDlmXBX3WOIcEsW/PastedGraphic-2.png.scaled.500.jpg" width="500" height="175"/&gt;&lt;/a&gt; &lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;Now Eclipse gives you this:&lt;/div&gt;  &lt;div&gt;&lt;div class="data syntax type-java"&gt;  &lt;table cellspacing="0" cellpadding="0"&gt; &lt;tr&gt; &lt;td&gt;  &lt;pre class="line_numbers"&gt; &lt;span rel="#L1" id="LID1"&gt;1&lt;/span&gt; &lt;span rel="#L2" id="LID2"&gt;2&lt;/span&gt; &lt;span rel="#L3" id="LID3"&gt;3&lt;/span&gt; &lt;span rel="#L4" id="LID4"&gt;4&lt;/span&gt; &lt;span rel="#L5" id="LID5"&gt;5&lt;/span&gt; &lt;span rel="#L6" id="LID6"&gt;6&lt;/span&gt; &lt;span rel="#L7" id="LID7"&gt;7&lt;/span&gt; &lt;span rel="#L8" id="LID8"&gt;8&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reverser&lt;/span&gt; &lt;span class="o"&gt;{&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="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;		&lt;span class="c1"&gt;// TODO Auto-generated method stub&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;		&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC6"&gt;	&lt;span class="o"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC8"&gt;&lt;span class="o"&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;/div&gt;  &lt;p /&gt;  &lt;div&gt;This is not only pretty bad, its retarded. Just run the test case and see for yourself. The only plausible result of this will be a NPE, and the NPE will happen in another class so you have to retrace your steps to find out where you need to fix it. I want my test case to throw me a stack that starts exactly where I need to continue developing. Even worse, if you're generating methods that are not invoked directly from a test case, this might lead to NPE's flying around in production. This will not do.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;So what can we do? Well, it's simple: just modify the template responsible. This template is called 'Method body' and should edit it to look something like this.&lt;/div&gt;  &lt;div&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/FWIS0zMl0PsPMxK82GqJvF8EOwdYC8aB6shc7BU2e7li1C41750iIGkWiVPY/PastedGraphic-7.png'&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iweinfuld/hPfZfyyPKMLZ9y24Y3lhszGYPZCCByOpIN9fjnqzdu3aKywdzDkKTZBH4oMd/PastedGraphic-7.png.scaled.500.jpg" width="500" height="84"/&gt;&lt;/a&gt; &lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;Now if you delete the generated method again and regenerate it, it should look better. &lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;&lt;div class="data syntax type-java"&gt;  &lt;table cellspacing="0" cellpadding="0"&gt; &lt;tr&gt; &lt;td&gt;  &lt;pre class="line_numbers"&gt; &lt;span rel="#L1" id="LID1"&gt;1&lt;/span&gt; &lt;span rel="#L2" id="LID2"&gt;2&lt;/span&gt; &lt;span rel="#L3" id="LID3"&gt;3&lt;/span&gt; &lt;span rel="#L4" id="LID4"&gt;4&lt;/span&gt; &lt;span rel="#L5" id="LID5"&gt;5&lt;/span&gt; &lt;span rel="#L6" id="LID6"&gt;6&lt;/span&gt; &lt;span rel="#L7" id="LID7"&gt;7&lt;/span&gt; &lt;span rel="#L8" id="LID8"&gt;8&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reverser&lt;/span&gt; &lt;span class="o"&gt;{&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="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;		&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UnsupportedOperationException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC5"&gt;				&lt;span class="s"&gt;&amp;quot;Iwein left this implementation as an exercise to the reader&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC6"&gt;	&lt;span class="o"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC7"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="line" id="LC8"&gt;&lt;span class="o"&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;/div&gt;  &lt;p /&gt;  &lt;div&gt;If we run the test case now it will fail. But the big improvement is that it will fail &lt;em&gt;correctly&lt;/em&gt;. What I mean by failing correctly is that the failure actually points out what is wrong: you have failed to implement a generated method. This is infinitely more informative than an NPE. As a bonus you can click the stack trace in the test and actually go to the method that you need to implement.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iweinfuld/K6QLZI0ERS9GHQdTOhDw2AFaIIhvFz8CGRlqPItLMpqlT01DyR3AGXWKB2MQ/PastedGraphic-8.png" width="423" height="154"/&gt; &lt;/div&gt;  &lt;div&gt;Just double click the line that is selected in the above screenshot. Pretty cool huh?&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;&lt;strong&gt;Catch blocks&lt;/strong&gt;&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;There is one more template I want you to modify. Check out the 'Catch block body' template. This is the template that gets used when you use the 'Surround with try/catch' quick fix. &lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iweinfuld/2KYEM9A0F2DbV7MoKFfrLflHfLw5xrGXTBkARkwRvnkE13BnM6rXkf3YRQNr/PastedGraphic-9.png" width="191" height="47"/&gt; &lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;The resulting code looks like this:&lt;/div&gt;  &lt;div&gt;&lt;div class="data syntax type-java"&gt;  &lt;table cellspacing="0" cellpadding="0"&gt; &lt;tr&gt; &lt;td&gt;  &lt;pre class="line_numbers"&gt; &lt;span rel="#L1" id="LID1"&gt;1&lt;/span&gt; &lt;span rel="#L2" id="LID2"&gt;2&lt;/span&gt; &lt;span rel="#L3" id="LID3"&gt;3&lt;/span&gt; &lt;span rel="#L4" id="LID4"&gt;4&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="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC2"&gt;			&lt;span class="c1"&gt;// TODO Auto-generated catch block&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC3"&gt;			&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;&lt;/div&gt;&lt;div class="line" id="LC4"&gt;		&lt;span class="o"&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;/div&gt;  &lt;p /&gt;  &lt;div&gt;I can tell you that there is&lt;em&gt; &lt;/em&gt;plenty of code like that running in production systems. Granted, &lt;a href="http://www.mindview.net/Etc/Discussions/CheckedExceptions"&gt;checked exceptions are hard to deal with&lt;/a&gt;, but surely we can do better than this.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;&lt;a href='http://posterous.com/getfile/files.posterous.com/iweinfuld/izitutU7sTFAFOGwOC9zeZtcQjCPqAadji1dqcMRPtErFLIOJwMcXvH6nlB5/PastedGraphic-10.png'&gt;&lt;img src="http://posterous.com/getfile/files.posterous.com/iweinfuld/4s0Cyt3nwxU1WwHD1ymx4RnRnLznmddz2EarpQpqNzGaPUVMuVJFd64ldMfA/PastedGraphic-10.png.scaled.500.jpg" width="500" height="92"/&gt;&lt;/a&gt; &lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;This isn't going to make your program run any better, but it sure is going to make it fail better. And that, dear reader is what this post is all about. If things fail early with an informative message, you (and those that come after you) are going to spend less time in a debugger and more time fixing actual problems. &lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;I've used Eclipse for the screenshots, but I can assure you that on my IDEA setup I have done the same fixes, and it wasn't very hard to figure out either. So now that you've read this there is no excuse to carelessly return null or print a stack trace anymore, even if you're not using Eclipse.&lt;/div&gt;  &lt;p /&gt;  &lt;div&gt;Don't be caught with an open fly again!&lt;/div&gt; &lt;p style="font-size: 10px;"&gt; &lt;a href="http://posterous.com"&gt;Posted via email&lt;/a&gt;  from &lt;a href="http://iweinfuld.posterous.com/excuse-me-your-fly-is-open"&gt;iweinfuld's posterous&lt;/a&gt; &lt;/p&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-9199285734508215818?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/9199285734508215818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=9199285734508215818' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/9199285734508215818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/9199285734508215818'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2010/05/excuse-me-your-fly-is-open.html' title='Excuse me, your fly is open'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-1359509514375429999</id><published>2009-10-11T00:58:00.000-07:00</published><updated>2009-10-11T22:13:42.602-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><category scheme='http://www.blogger.com/atom/ns#' term='junit'/><category scheme='http://www.blogger.com/atom/ns#' term='springingetration'/><title type='text'>Combining TemporaryFolder @Rule with Spring 3</title><content type='html'>I like TDD, I like Springs @ContextConfiguration framework and I like JUnit 4.7's new Temporary folder. Getting the latter two to play nice isn't as easy as I hoped, so here's an attempt at a way to make them work.&lt;br /&gt;&lt;br /&gt;Let's say you need to configure an incoming directory on a component using external configuration. For example in Spring Integration: &lt;span style="font-family:courier new;"&gt;&lt;file:inbound-channel-adapter channel="incomingChanges" directory="#{config.directories.store}" filter="onlyNewChangesFilter"&gt;&lt;/file:inbound-channel-adapter&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;file:inbound-channel-adapter directory=#{config.directories.store} ... /&gt;&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I'm using expression language to load a property from a config object, which I wire in turn as a Spring bean. In my main application this config object can just be a &lt;span style="font-family:courier new;"&gt;&lt;util:properties&gt;&lt;/util:properties&gt;&lt;/span&gt; for example, and in my test I can override that bean with an inner class from my test.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    public static class Config {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        public static final Map&lt;string,&gt; directories = new HashMap&lt;string,&gt;();&lt;/string,&gt;&lt;/string,&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;    }&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you then use the containing context in a JUnit test it will be loaded up once the context is created, so you need to make sure to put the store value in the map &lt;span style="font-family:courier new;"&gt;@BeforeClass&lt;/span&gt;. Now I'd like to use a &lt;span style="font-family:courier new;"&gt;TemporaryFolder&lt;/span&gt;, to store files in the input directory of the channel adapter, but you can't refresh the property of a singleton bean each test. The @Rule will be applied before each test, resulting in the second test using a different directory from the context. A shame.&lt;br /&gt;&lt;br /&gt;A working solution is to just remove the &lt;span style="font-family:courier new;"&gt;@Rule&lt;/span&gt; annotation from the &lt;span style="font-family:courier new;"&gt;TemporaryFolder&lt;/span&gt; and manually invoke &lt;span style="font-family:courier new;"&gt;create()&lt;/span&gt; and &lt;span style="font-family:courier new;"&gt;delete()&lt;/span&gt;. I'd like to know if there is a better solution.&lt;br /&gt;&lt;br /&gt;Maven sample project can be found on &lt;a href="http://github.com/iwein/Spring-Integration-Sandbox/tree/master/quick-samples/"&gt;GitHub&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If you give it a go, let me know if you find a neater option!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-1359509514375429999?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/1359509514375429999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=1359509514375429999' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1359509514375429999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1359509514375429999'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2009/10/combining-temporaryfolder-rule-with.html' title='Combining TemporaryFolder @Rule with Spring 3'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-283089129242039336</id><published>2009-09-04T04:28:00.000-07:00</published><updated>2009-09-04T05:12:55.873-07:00</updated><title type='text'>Spring Milestones and Snapshots with maven</title><content type='html'>It took me way longer than I wanted to set up a simple maven project using the Spring M4 and the latest snapshot of Spring Integration. For some reason this is not documented prominently on &lt;a href="http://www.springsource.org/about"&gt;springframework.org&lt;/a&gt;. I commit on Spring Integration, so maybe I should do something about this, on the other hand, blogging is easier... I'll hand you the fix that still worked for me in 2009.&lt;br /&gt;&lt;br /&gt;I'm a bit of a maven rookie. I've been using it for years now, but I still feel uncomfortable using it and I have given up on ever having a complete grasp of how it works. The general idea and functionality I understand and sympathize with, but other than that it's too painful to recommend. On the other hand, I just want my build to work and learning Gradle isn't on the top of my list if I need to get started &lt;span style="font-weight: bold;"&gt;now&lt;/span&gt;. Maven itself is tolerable but the plugin and repository landscape isn't.&lt;br /&gt;&lt;br /&gt;I'm just going to save you 45 (if not more) minutes of searching and cursing before you find hints on the project pages.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Don't&lt;/span&gt; use the search tools for maven central (I like &lt;a href="http://mvnrepository.com/"&gt;mvnrepository&lt;/a&gt;) for Spring dependencies.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Don't&lt;/span&gt; use SpringSources enterprise repository for milestones and snapshots. They might be there, but they end up there later than on S3.&lt;br /&gt;&lt;br /&gt;There is a milestone and snapshot repository in S3, as described by Ben Hale in a &lt;a href="http://blog.springsource.com/2007/09/18/maven-artifacts-2/"&gt;blog&lt;/a&gt;. Use the repository snippets from that blog (also included here). Look carefully at the url of the s3browser.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Do use&lt;/span&gt; &lt;a href="http://s3browse.com/explore/maven.springframework.org/"&gt;http://s3browse.com/explore/maven.springframework.org/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The repositories are in s3, and while that is very cool, it's also a pain for you because you can't explore them with the url copied from the repository element. Keep a comment on that in your pom if you have colleagues.&lt;br /&gt;&lt;pre&gt;&amp;lt;repository&gt;&lt;br /&gt; &amp;lt;id&gt;spring-milestone&amp;lt;/id&gt;&lt;br /&gt; &amp;lt;name&gt;Spring Portfolio Milestone Repository&amp;lt;/name&gt;&lt;br /&gt; &amp;lt;url&gt;http://s3.amazonaws.com/maven.springframework.org/milestone&amp;lt;/url&gt;&lt;br /&gt; &amp;lt;!-- browse via http://s3browse.com/explore/maven.springframework.org/milestone --&gt;&lt;br /&gt;&amp;lt;/repository&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;repository&gt;&lt;br /&gt; &amp;lt;id&gt;spring-snapshot&amp;lt;/id&gt;&lt;br /&gt; &amp;lt;name&gt;Spring Portfolio Snapshot Repository&amp;lt;/name&gt;&lt;br /&gt; &amp;lt;url&gt;http://s3.amazonaws.com/maven.springframework.org/snapshot&amp;lt;/url&gt;&lt;br /&gt; &amp;lt;!-- browse via http://s3browse.com/explore/maven.springframework.org/snapshot --&gt;&lt;br /&gt;&amp;lt;/repository&gt;&lt;/pre&gt;&lt;br /&gt;If you need artifacts from S2's enterprise repository too you can end up with a whopping 6 repository snippets just for your spring artifacts. Keeping track of which artifact comes from which can be daunting. If you're in the position to do so, using &lt;a href="http://nexus.sonatype.org/"&gt;Nexus&lt;/a&gt; (or similar) can be used to mitigate that.&lt;br /&gt;&lt;br /&gt;There are a lot more details to all this (related to OSGi and maven versioning schemes), but if you're just interested in making it work, you should be grand now.&lt;br /&gt;&lt;br /&gt;Hope this helps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-283089129242039336?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/283089129242039336/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=283089129242039336' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/283089129242039336'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/283089129242039336'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2009/09/spring-milestones-and-snapshots-with.html' title='Spring Milestones and Snapshots with maven'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-6403445123805434498</id><published>2009-01-10T03:20:00.000-08:00</published><updated>2009-01-11T02:59:44.982-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mailing lists'/><category scheme='http://www.blogger.com/atom/ns#' term='corporate spam'/><category scheme='http://www.blogger.com/atom/ns#' term='rss'/><title type='text'>Push vs. Pull or Why company mailing lists are evil</title><content type='html'>Everybody that works for a large organization knows the semi Observer anti-pattern. In some form or another at least. It works like this: The Big Boss thinks that you need to know, so he pushes information to you through email. He is too lazy to push this corporate spam to all personnel individually so you get added to a list automatically. At least some of your bosses don't know that there is such a thing as BCC so soon all personnel knows all the lists they are on.&lt;br /&gt;&lt;br /&gt;The next step is that people start holding discussions using the email addresses for those lists. I've seen these types of discussions spiral out of control in different firms I've worked for. This causes unreasonable load and distraction for the employees and can even cause the whole &lt;a href="http://hosted.ap.org/dynamic/stories/S/STATE_DEPARTMENT_E_MAIL?SITE=AP&amp;amp;SECTION=HOME&amp;amp;TEMPLATE=DEFAULT"&gt;email system to collapse under the strain&lt;/a&gt;. I can tell you this is not the first time something like this has happened.&lt;br /&gt;&lt;br /&gt;What makes this behavior unforgivable, is that there is such a simple solution.&lt;br /&gt;&lt;br /&gt;Use RSS or newsgroups to let people subscribe to replacements for these lists and clearly separate directed communications (to a few people) from news and open discussions. By using this simple solution (and working for a company that actually does this right), I've managed to reduce my incoming email by 80%. It is still some work to go through all the mails after a few days of inactivity, but the thing is it is not absolutely impossible anymore.  The other immensely satisfying improvement is that most mail I get I actually &lt;span style="font-style: italic;"&gt;want&lt;/span&gt; to read.&lt;br /&gt;&lt;br /&gt;I do have thousands of unread items piling up in my RSS reader and nntp client, but those I know I can safely discard when they get stale. They don't eat up disk space and I can always search them.&lt;br /&gt;&lt;br /&gt;There are reasons to keep lists in the company anyway. For example some employees are too lazy or stupid to subscribe to RSS lists and newsgroups, if you are legally required to send out a communique an email push might come in handy. In those cases: &lt;span style="font-weight: bold;"&gt;use BCC&lt;/span&gt;. If something should not be done, make it impossible. Guidelines for Reply-All and the pleas and threats to follow them are just more unneccesary noise.&lt;br /&gt;&lt;br /&gt;So bosses all over the world, if you read this: be smart and stop spamming your employees, they hate you for it and they're right.&lt;br /&gt;&lt;br /&gt;I saw &lt;a href="http://www.techcrunch.com/2008/03/23/a-crisis-in-communication/"&gt;another complaint about many emails in general&lt;/a&gt;. I bet that this guy is subscribed to his own blog using email. He ends his post with:&lt;br /&gt;&lt;blockquote&gt;If you are the person with the idea to save us all, send me an email and tell me all about it. Actually, strike that. Drop by my house and tell me all about it. I don’t want your message to get lost in my inbox&lt;br /&gt;&lt;/blockquote&gt;I'm not a venture capitalist, but still the difference is striking: my mailbox is completely read, and I spend less than an hour a day to keep it that way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-6403445123805434498?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/6403445123805434498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=6403445123805434498' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/6403445123805434498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/6403445123805434498'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2007/05/push-vs-pull-or-why-mailing-lists-are.html' title='Push vs. Pull or Why company mailing lists are evil'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-9211291272792851026</id><published>2008-10-12T01:07:00.000-07:00</published><updated>2008-10-12T02:04:29.235-07:00</updated><title type='text'>Syncing calendars... nothing is ever easy</title><content type='html'>I have a problem of managing multiple callendars. My wife has access to my Google calendar, my company has access to my Zimbra calendar.  I use a Mac, and I like to use iCal if possible. I use Plaxo, TripIt and Dopplr, which provide ical interfaces/synchronisation, just like Google and Zimbra.&lt;br /&gt;&lt;br /&gt;All this shouldn't be too original, so I expect that other people have this problem. Granted it is not an easy problem to solve, because synchronisation isn't easy. Let me first explain how I'm managing things now (and how I screw up). Then go over the options and then over what I really want.&lt;br /&gt;&lt;br /&gt;Now I manage my calendars through CalDav. This works really well for a single calendar, but it does nothing for you in terms of synchronisation. If my office manager add's an appointment I see it show up in the right calendar, if I get a trip confirmation and send it to TripIt same story if my wife makes an appointment I can see it show up too. Nice overview, clear separation of calendars. Perfect, as long as I do the managing. That is the problem, my wife manages the calender of our private life, my manager manages the calender for the jobs. They have no idea what the other is doing.&lt;br /&gt;&lt;br /&gt;So I screw up like this: if my manager plans for me to be abroad he checks with me and puts it in the calendar, then I have to make sure it shows in my private calendar that I'm abroad, otherwise my wife will plan something conflicting in the home calendar.&lt;br /&gt;&lt;br /&gt;The underlying problem is that I am just one person, so everybody planning for me to be somewhere needs visibility on where I am. Main options:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Be more disciplined and copy things over&lt;/li&gt;&lt;li&gt;Use a single calendar and synchronize&lt;/li&gt;&lt;/ul&gt;The first option is what I'm doing now. Fine tuning this would mean I create a single calendar that lists my availability and make sure that all planners have read access to that from a single interface that they use for planning. The advantage is that this way the planners do not have to worry about fine grained appointments, just about available time (in a certain location).&lt;br /&gt;&lt;br /&gt;The second option would allow me to be very lazy, but it would also result in a privacy issue where my manager can see that I went to a party on thursday evening or something. I don't care that much about privacy. I do care about my manager moving around my dentist appointment from the private calendar, so the solution is not ideal.&lt;br /&gt;&lt;br /&gt;An ideal situation would allow me to share availability across calendars, and restrict write access and access to detailed information based on different calendars/sets of appointments.&lt;br /&gt;&lt;br /&gt;The annoying thing is that there are no tools that allow this. Requirements are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Have to use Zimbra for work&lt;/li&gt;&lt;li&gt;Have to use Gcal for private&lt;/li&gt;&lt;li&gt;Want to use iCal as interface&lt;/li&gt;&lt;li&gt;Want to integrate CalDav calendars&lt;br /&gt;&lt;/li&gt;&lt;li&gt;No manual syncing&lt;/li&gt;&lt;/ul&gt;The only way to get close would be to install different sync utilities for my mac and sync with a local calendar. The proper way to do it is to allow CalDAV calendars to be synced in ical, but there is no support for this in iCal natively. The only workable solution (other than discipline) is to run sync utilities like Spanning Sync and the Zimbra iCal plugin. This is bound to screw up my calendars at some point I'm sure...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-9211291272792851026?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/9211291272792851026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=9211291272792851026' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/9211291272792851026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/9211291272792851026'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2008/10/syncing-calendars-nothing-is-ever-easy.html' title='Syncing calendars... nothing is ever easy'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-3156190031428627635</id><published>2008-08-23T01:03:00.000-07:00</published><updated>2009-09-04T04:28:09.895-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='subclipse springsource ganymede eclipse mac leopard'/><title type='text'>Update svn on Leopard to play nice with subclipse</title><content type='html'>Not so long ago I moved forward to STS 1.1 which is based on Eclipse 3.4 Ganymede. Of course I needed a svn plugin and then I ran into &lt;a href="http://beerholder.blogspot.com/2008/06/eclipse-34-ganymede-and-subclipse-14.html"&gt;this issue&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Mac OSx packages an old version of collabnet subversion (1.4.x). And that doesn't play nice with subclipse. The fix suggested there is to use an old version because:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;For Windows users, it is a simple matter of installing the new Subversion 1.5 client and making sure JavaHL is on the path. For Unix users, this workaround obviously defeats the purpose of having a distro with package management and requires manual installation of the libraries in the correct locations.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If you truly understand that and it is a blocking concern for you (notice the hint of sarcasm), don't read on. There is however a very simple solution to run the right version and just make it work.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download and install &lt;a href="http://www.collab.net/downloads/apple/download.html"&gt;http://www.collab.net/downloads/apple/download.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:courier new;"&gt;sudo rm /usr/bin/svn*&lt;/span&gt; (you might want to check if you haven't got any other programs named svn* before you do this)&lt;/li&gt;&lt;/ol&gt;The second step is needed because the collabnet package installs simlinks into /usr/local/bin and the programs in /user/bin take precedence.&lt;br /&gt;&lt;br /&gt;Once this is done you're good to go, &lt;span style="font-weight: bold;"&gt;and&lt;/span&gt; with the latest versions.&lt;br /&gt;&lt;br /&gt;Update: I've moved on to do this with MacPorts, lately their svn versions are fine, and the installation is much simpler.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-3156190031428627635?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/3156190031428627635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=3156190031428627635' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3156190031428627635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/3156190031428627635'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2008/08/update-svn-on-leopard-to-play-nice-with.html' title='Update svn on Leopard to play nice with subclipse'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-2102685910805973821</id><published>2008-08-20T00:43:00.000-07:00</published><updated>2008-08-20T01:07:51.024-07:00</updated><title type='text'>Correct Simple Singletons</title><content type='html'>This is going to be a very short blog. It's not about concurrency. It's about avoiding to think about concurrency. As was the original intent of this blog it is about being lazy, but still not being wrong.&lt;br /&gt;&lt;br /&gt;Yesterday I read a very old blog while digging through the web for reasons to be scared of the volatile keyword. I found plenty, but this one is a gem: &lt;a href="http://blogs.msdn.com/brada/archive/2004/05/12/volatile-and-memorybarrier.aspx."&gt;http://blogs.msdn.com/brada/archive/2004/05/12/volatile-and-memorybarrier.aspx.&lt;/a&gt; It's about .Net code, but the basic problems also apply in Java. The link to &lt;a href="http://www.cs.umd.edu/%7Epugh/java/memoryModel/DoubleCheckedLocking.html"&gt;http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html&lt;/a&gt; is worth a read too.&lt;br /&gt;&lt;br /&gt;If you can think about concurrency but you don't want to do it every day like me adhere to these rules when writing singletons:&lt;br /&gt;&lt;br /&gt;When you plan on using the singleton write:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;&lt;pre&gt;public class Singleton {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  private static final instance = new Singleton();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;  private Singleton() {}&lt;br /&gt;  public static Singleton get() {&lt;br /&gt;    return instance;&lt;br /&gt;  }&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/pre&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When you don't plan on using the singleton, but you still feel the urge to implement it write:&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;span style="font-family: courier new;"&gt;&lt;br /&gt;&lt;pre&gt;public class Singleton {&lt;/span&gt;&lt;br /&gt; &lt;span style="font-family: courier new;"&gt;  private static instance;&lt;/span&gt;&lt;br /&gt; &lt;span style="font-family: courier new;"&gt;  private Singleton() {}&lt;br /&gt;  public static synchronized Singleton get() {&lt;br /&gt;    return instance;&lt;br /&gt;  }&lt;br /&gt; &lt;/span&gt;&lt;span style="font-family: courier new;"&gt;}&lt;/pre&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When you're not going to use the singleton a lot, it is probably more memory efficient to just use a disposable instance, hence removing the need for the singleton at all. So the recipe goes like this:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Don't use a singleton if you don't need to&lt;/li&gt;&lt;li&gt;Use the simple (static final) variant if you do need a singleton&lt;/li&gt;&lt;li&gt;Use the synchronized variant if you are intent on going on the downward slope&lt;/li&gt;&lt;li&gt;Of course you are special, so go on and do it the hard way.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-2102685910805973821?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/2102685910805973821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=2102685910805973821' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2102685910805973821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2102685910805973821'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2008/08/correct-simple-singletons.html' title='Correct Simple Singletons'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-1758344166527682820</id><published>2008-07-09T10:18:00.000-07:00</published><updated>2008-07-09T10:35:25.048-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='syntax'/><category scheme='http://www.blogger.com/atom/ns#' term='DRY'/><category scheme='http://www.blogger.com/atom/ns#' term='TDD'/><title type='text'>Don't repeat yourself, just quote yourself.</title><content type='html'>I just read an &lt;a href="http://dannorth.net/2008/06/let-your-examples-flow"&gt;article by Dan North about how the DRY principle doesn't work with Test code&lt;/a&gt;. Obviously I agree with him, because it is almost trivial once you've figured it out on your own. I already met many people that did and were quite happy with themselves for it, actually that could have been me after I had about 1 year of experience with TDD.&lt;br /&gt;&lt;br /&gt;When I read the linked blog I mused over the main counter argument against dropping DRY, it is actually the argument to adopt it: what about the maintenance hell of all that repeated code. Arguably if you use proper mocking or stubbing (especially mocking) you shouldn't have too much trouble with this, but wouldn't it be nice if there was a solution for this?&lt;br /&gt;&lt;br /&gt;So what are the requirements:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;We want to get readable code (not requiring you to constantly switch source files or scroll)&lt;/li&gt;&lt;li&gt;We want little writing effort (not repeating the same code snippet over and over)&lt;/li&gt;&lt;/ol&gt;Requirement 2. is covered by OO, AOP and friends, but they completely ruin 1. in certain scenarios (e.g. test code). To get 1. you will have to drop 2... NOT good enough!&lt;br /&gt;&lt;br /&gt;I am a fan of wikis and as you might know many have a feature called templates that specifically targets these two requirements. How about template in code. Just add a template construct and let the IDE optionally show the actual code inline.&lt;br /&gt;&lt;br /&gt;I like it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-1758344166527682820?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/1758344166527682820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=1758344166527682820' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1758344166527682820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/1758344166527682820'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2008/07/dont-repeat-yourself-just-quote.html' title='Don&apos;t repeat yourself, just quote yourself.'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-2869118675883393091</id><published>2008-03-25T04:48:00.000-07:00</published><updated>2008-03-25T05:20:25.231-07:00</updated><title type='text'>My first mobile internet</title><content type='html'>I've just replaced my well over 4y old battle scarred Nokia 6100. It's not that it was really broken, but just that my definition of 'the basic necessities' has changed. Let me give an overview of the definition over the years:&lt;br /&gt;&lt;br /&gt;In 1998 when I bought my first mobile phone:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Be able to make a call&lt;/li&gt;&lt;/ol&gt;In 2004 when I got my third phone:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Be able to make a call&lt;/li&gt;&lt;li&gt;Be able to use sms&lt;/li&gt;&lt;li&gt;Battery life at least 1 week/4h calling&lt;/li&gt;&lt;/ol&gt;In 2008:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Be able to make a call&lt;/li&gt;&lt;li&gt;Be able to use sms&lt;/li&gt;&lt;li&gt;Be able to connect my laptop to internet&lt;/li&gt;&lt;li&gt;Battery life 1 week&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Now in 2008 I have a job that requires me to travel and I "need" to have internet at all times. I decided to do what operators have been blabbing about for 6 years now and combine my phone needs with my internet needs. We do have UMTS now so it should be OK, right? Right...&lt;br /&gt;&lt;br /&gt;To put things into perspective I will just give some hints to how my 'basic' internet needs are pretty far advanced compared to my phone needs. I for example:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;expect ANY website to render in under 0.5 seconds&lt;/li&gt;&lt;li&gt;routinely download files over 300M and don't expect to wait longer than it takes for me to get coffee.&lt;/li&gt;&lt;li&gt;store my complete life (contacts, documents, ...) online and don't expect to notice the difference.&lt;/li&gt;&lt;/ul&gt;So I got myself a unlimited data subscription and a UMTS capable phone (SE W660i if anyone cares). And I started connecting it to the internet.&lt;br /&gt;&lt;br /&gt;Many geeks will look pitiful at my incompetence, but it took me 4 hours to get things working. Kudo's to &lt;a href="http://www.taniwha.org.uk/"&gt;http://www.taniwha.org.uk/&lt;/a&gt; and the guys from SE for doing my providers and Apple's work for them. Funny that the guys that get the most money from me (Apple) are the least helpful in getting things to work properly. Ah well, I should have gotten an iphone, but that doesn't have umts... anyway, that's a whole different rant.&lt;br /&gt;&lt;br /&gt;Now that everything works I am just curious at the speed I can get out of my new toys (&lt;a href="http://text.dslreports.com"&gt;http://text.dslreports.com&lt;/a&gt;):&lt;big&gt;&lt;br /&gt;&lt;/big&gt;&lt;big&gt;&lt;/big&gt;&lt;blockquote&gt;&lt;big&gt;40 kbit/sec&lt;/big&gt;&lt;br /&gt;1.978s latency&lt;/blockquote&gt;&lt;br /&gt;Erm.. Those guys from telfort are really missing the point here I think. WTF!&lt;br /&gt;&lt;br /&gt;When I made webpages last millennium the general rule was to keep images under 100k so that with this speed it would take me, say 20 seconds PER IMAGE to load the page.&lt;br /&gt;&lt;br /&gt;I looked at &lt;a href="http://www.umtsworld.com/technology/dataspeed.htm"&gt;http://www.umtsworld.com/technology/dataspeed.htm&lt;/a&gt; and the theoretical maximum is still pretty disappointing...&lt;br /&gt;&lt;br /&gt;It's 2008 dammit, where is my flying car!&lt;blockquote&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-2869118675883393091?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/2869118675883393091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=2869118675883393091' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2869118675883393091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/2869118675883393091'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2008/03/my-first-mobile-internet.html' title='My first mobile internet'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-5786991395381375620</id><published>2007-05-22T04:28:00.000-07:00</published><updated>2007-05-23T13:52:36.730-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hibernate'/><category scheme='http://www.blogger.com/atom/ns#' term='dwr'/><category scheme='http://www.blogger.com/atom/ns#' term='spring'/><title type='text'>Comparing beans or why equality is subjective</title><content type='html'>In my project I use Hibernate and DWR so between my database and application I have to deal with Hibernate fiddling with my objects and between my client (browser) and application I have to deal with the DWR.&lt;br /&gt;&lt;br /&gt;This all seems well and fine and generally it is. In fact kudos are in order.&lt;br /&gt;&lt;br /&gt;However, there is no need to list all the key features again, you can just check the websites of the products for that. What I would like to describe is the fundamental problem of comparing objects that these frameworks do &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; solve.&lt;br /&gt;&lt;br /&gt;The essence of the problem is that in a pure object oriented environment all objects have &lt;span style="font-style: italic;"&gt;identity &lt;/span&gt;(== in Java) and when you go beyond the boundaries of your environment that law doesn't apply anymore.  In other words: once&lt;br /&gt;your application let's go of an object, that object is gone forever. To illustrate an example is appropriate.&lt;br /&gt;&lt;br /&gt;Say in my application I have some simple user management. A User object can be persisted to the database and retrieved when a user logs in. The user can edit his profile (user properties) in the client and since I'm using Ajax i don't want the user to have to reload and redo his changes if I restart my application.&lt;br /&gt;&lt;br /&gt;In real life each user is unique, so I expect the same from my application, database and client. Sounds simple, but it isn't. First let's have a look at the hibernate persistence layer. In the relational database there is no identity by default (it is impossible to distinguish two records with the exact same columns). This is easily fixed by adding a primary key to the table. Hibernate can do this for you. You just have to put some sort of Id property on your Pojo and tell Hibernate to use a sequence to fill in this property once the object is saved (eww).&lt;br /&gt;Now there are three ways to obtain an object:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;create it yourself &lt;/li&gt;&lt;li&gt;get it from hibernate&lt;/li&gt;&lt;li&gt;get it from somewhere else (the client)&lt;/li&gt;&lt;/ol&gt;In the first case the Id will not be initialized (obviously, because Hibernate is in charge of that). In the second case the Id will definitely be initialized, otherwise the pk constraint would be violated. The third case is arbitrary. If the client got the object from the application in the first place there is a good chance that it has been saved before. In that case the client better keep track of the id.  If the client is trying to create a new user there will not be an id.&lt;br /&gt;&lt;br /&gt;Actually it is even a bit more complicated, as I might want to allow the application to pass objects to the client before they are saved. In this scenario the client and the application need to be able to negotiate identity between objects without polluting the id property that Hibernate needs to fill once the object gets saved. (If you get lost here it is probably a good idea to read up on &lt;a href="http://www.hibernate.org/109.html."&gt;Hibernate and the equals() method&lt;/a&gt;.)&lt;br /&gt;&lt;br /&gt;Now take a note that I have been talking about identity and equality. Equality is the functional identity (i.e. two distinct objects in the jvm could be representing the same object from the users perspective).&lt;br /&gt;&lt;br /&gt;If a user loads his User object in the client and after some changes he hits the save button, the application needs to be able to see that the existing User with a certain identity should be saved (resulting in a database update). You could establish this behavior with a smart implementation of the equals() method.&lt;br /&gt;&lt;br /&gt;It is important to make a clear distinction between functional equality and technical identity. To illustrate suppose the application is a friends network. One user is logged in and updating his details. Another user is logged in and adding the first user to his network to do this he fills in the user form, the client sends the new user object to the application. The application needs to check if the user is equal to a known user to prevent duplication. Also there need to be two different instances of the first user. The identity of these user objects needs to be managed over the DWR pipes.&lt;br /&gt;&lt;br /&gt;Now we have two objects in our application that are functionally equal, but technically distinct. This exposes the problem I'm trying to get at. Since the two objects are equal, but not identical  either updates done in the first session do not show up in the second or you would have to constantly manage conflicting changes when either user saves the object.&lt;br /&gt;&lt;br /&gt;Elegant solutions are most welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-5786991395381375620?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/5786991395381375620/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=5786991395381375620' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/5786991395381375620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/5786991395381375620'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2007/05/comparing-beans-or-why-equality-is.html' title='Comparing beans or why equality is subjective'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-8743024676725858231</id><published>2007-04-25T01:48:00.000-07:00</published><updated>2007-06-07T05:33:33.800-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DSL'/><category scheme='http://www.blogger.com/atom/ns#' term='LOP'/><title type='text'>What happened to LOP?</title><content type='html'>Wouter attended me to this &lt;a href="http://www.onboard.jetbrains.com/is1/articles/04/10/lop/"&gt;interesting article&lt;/a&gt; by Sergey Dmitriev. Blunt axe summary: Language oriented programming will allow the programmer to naturally create DSL's as the need arises. Using the OO paradigm where applicable, using other paradigms in other domains. This will keep the code look more like the design and less like the unreadable crap that we normally write. Be honest: your beautiful creations are not exactly poetry to the untrained eye, right?&lt;br /&gt;&lt;br /&gt;There are some more articles about it primarily the one by &lt;a href="http://www.martinfowler.com/articles/languageWorkbench.html"&gt;Martin Fowler&lt;/a&gt;, but nothing new really since 2005.&lt;br /&gt;&lt;br /&gt;My theory is that getting an application (damn thing) to work it is just too much fuss to use something like MSP. The potential maintenance hell will lead managers to the conclusion that sticking to skills that they have sent their programmers to trainings for will be better. Who hasn't been to that design meeting where somebody started by drawing a very familiar picture on the whiteboard and said: "This is the service layer, this is the business layer, this is the data layer ...."? After that meeting everybody takes their template design documents, SLA's, status updates... and starts filling in the name of the project.&lt;br /&gt;&lt;br /&gt;Creativity should be done by humans, filling in templates should be done by computers. But in the end humans tend to favor familiar territory. To be perfectly honest, most of my hours are spent doing stuff that should be automated.&lt;br /&gt;&lt;br /&gt;Anyways, it would be nice if this LOP made it's way into mainstream software development. Time to polish up those true programming skills and forget about the compiler in the back of your head that you shouldn't rely on anyway.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-8743024676725858231?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/8743024676725858231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=8743024676725858231' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/8743024676725858231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/8743024676725858231'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2007/04/what-happened-to-lop.html' title='What happened to LOP?'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-764237810137207640.post-8178033473040818051</id><published>2007-04-13T06:07:00.000-07:00</published><updated>2007-04-13T06:30:08.536-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='subclipse'/><title type='text'>Subclipse annoyance</title><content type='html'>To help the unwary that will follow in my footsteps:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;How to change the stored credentials for a subversion repository in Eclipse (using Subclipse)&lt;br /&gt;&lt;/span&gt;Subclipse is a wonderfull tool that helps a bunch when working with eclipse on a svn repo. However there are annoyances. This one i lost an hour on today.&lt;br /&gt;&lt;br /&gt;Imagine that you have a friend that starts working on your machine and checks out a project. While he's working he doesn't want to provide credentials on every commit so he checks the save-pass checkbox. Now you have a project on which all commits get done as his user. Now you want to continue working on the project after he's gone. But you don't want to assume his identity. You need to remove/change the stored credentials. And if possible you don't want to do it with a nice button or option in the menu... Don't get your hopes up :/&lt;br /&gt;&lt;br /&gt;So you try:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;fiddling with the properties of the project -&gt; no luck&lt;/li&gt;&lt;li&gt; fiddling with the properties of the location in the repository explorer -&gt; no luck&lt;/li&gt;&lt;li&gt;deleting the repository and recreating it&lt;/li&gt;&lt;li&gt;deleting the project and recreating it&lt;/li&gt;&lt;li&gt;combinations of 3 and 4 laced with power cycles -&gt; no luck&lt;/li&gt;&lt;/ol&gt;The problem is hinted at here &lt;a href="http://svn.haxx.se/subusers/archive-2006-08/0030.shtml"&gt;http://svn.haxx.se/subusers/archive-2006-08/0030.shtml&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Another problem you're experiencing is that subclipse uses JavaHL or SVNKit for the connection. These adapters are conveniently storing credentials for you. Subclipse doesn't care and doesn't provide an interface to influence this.&lt;br /&gt;&lt;br /&gt;If you don't want to look for the config files and "fix" it from the comfort of eclipse. You can around this by just switching interfaces from Window-&gt;Preferences-&gt;Team-&gt;SVN&lt;br /&gt;(Otherwise just go on and fiddle with the authentication files as described in the link)&lt;br /&gt;&lt;br /&gt;Well, how's that for a bit of useless information?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/764237810137207640-8178033473040818051?l=iweinfuld.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://iweinfuld.blogspot.com/feeds/8178033473040818051/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=764237810137207640&amp;postID=8178033473040818051' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/8178033473040818051'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/764237810137207640/posts/default/8178033473040818051'/><link rel='alternate' type='text/html' href='http://iweinfuld.blogspot.com/2007/04/subclipse-annoyance.html' title='Subclipse annoyance'/><author><name>Iwein</name><uri>http://www.blogger.com/profile/03894314935422437500</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_kiIoDvqiqKE/SqEN_K0maFI/AAAAAAAABNo/do8Ws6FNRCA/s1600-R/c6019cc613abada6ce14018ab86ac3a1.png'/></author><thr:total>0</thr:total></entry></feed>
