<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>JoergM.com</title>
	
	<link>http://www.joergm.com</link>
	<description>Agile software development and more by Joerg Mueller</description>
	<lastBuildDate>Sun, 14 Aug 2011 14:08:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/Joergmcom" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="joergmcom" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Continuous Deployment changes your mind</title>
		<link>http://www.joergm.com/2011/08/continuous-deployment-changes-your-mind/</link>
		<comments>http://www.joergm.com/2011/08/continuous-deployment-changes-your-mind/#comments</comments>
		<pubDate>Sun, 14 Aug 2011 14:06:33 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[agile]]></category>
		<category><![CDATA[continuous delivery]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[continuous deployment]]></category>
		<category><![CDATA[discipline]]></category>
		<category><![CDATA[practice]]></category>

		<guid isPermaLink="false">http://www.joergm.com/?p=478</guid>
		<description><![CDATA[We are practicing Continuous Deployment since about a year. When looking back I realize the dramatic way this practice changed the way we work. Just to draw the fine line between Continuous Delivery and Continuos Deployment I use the definition I once heard from Neal Ford. Continuous Delivery allows you to deploy every commit but [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2011%2F08%2Fcontinuous-deployment-changes-your-mind%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2011%2F08%2Fcontinuous-deployment-changes-your-mind%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>We are practicing Continuous Deployment since about a year. When looking back I realize the dramatic way this practice <strong>changed the way we work</strong>.</p>
<p>Just to draw the fine line between Continuous Delivery and Continuos Deployment I use the definition I once heard from Neal Ford. Continuous Delivery allows you to deploy every commit but you don&#8217;t do it every time. With Continuous Deployment you go further and really deploy every time.</p>
<p>I have recently been asked what the benefits of Continuous Deployment are compared to Continuous Delivery. I think the <strong>impact on your development practice</strong> is a huge thing.</p>
<p>In our company we practice agile development since about 2005. During that time I can remember many discussions about agile practices like:</p>
<ul>
<li>Test Driven Development</li>
<li>Definition of Done</li>
<li>Potentially Shippable Product</li>
<li>Refactoring in baby steps</li>
<li>Not committing on a red build</li>
</ul>
<p>Many of them <strong>do not easily reveal their benefits</strong> in daily business. So it becomes difficult to use them consequently.</p>
<p>The Definition of Done is a great example. It is easy to declare something finished or appropriately tested when there is usually a QA department that will find your mistakes during release tests. So the common recipe is write down your definition, post it on the wall and <strong>&#8220;be more disciplined&#8221;</strong>. Force yourself to write more tests, force yourself to declare things done only if they are really done and so on. This is not easy. In my experience <strong>it seldom works</strong>.</p>
<p>This changes dramatically when using continuous deployment. Between your commit and the production system is only an automated deployment pipeline, that usually takes something around 30 minutes. <strong>There is no QA department</strong> that does a extensive release test. Your mistakes will only be found by automated test that you wrote yourself. Well or they will be found by your Users.</p>
<p>Automated tests become your <strong>safety net</strong>. This again changes the way you think about TDD. It totally makes sense to have a near full coverage of your code. It also makes sense to have integration tests on API and GUI level to make sure your deployment pipeline catches most mistakes. It will not catch any mistake, but in my experience the same is true for most QA departments.</p>
<p>You will think differently about Potentially Shippable Products. Every commit has to be shippable and <strong>it will (not only potentially) be shipped</strong>.</p>
<p>This forces working in baby steps. It is just not possible to refactor a system by destroying it for several days.</p>
<p>If a <strong>build is red</strong> the deployment pipeline is halted. Nobody is able to apply more changes to the system unless this problem is fixed. Again something that used to be <strong>a discipline thing becomes a necessity</strong>. You need to help your teammates to fix the problem otherwise you can&#8217;t work yourself. The same is true if there is a red build in the evening. One of my teammates even talks about an <strong>addiction to fix the build</strong> before going home. It just gives you a good feeling to finish your day in a green state.</p>
<p>Continuous Delivery has several immediate business benefits I might tell you about another time. But most of them don&#8217;t need every commit to be deployed.</p>
<p>But I think the impact of deploying every commit on your development practice huge. Many agile practices <strong>make so much more sense.</strong> They fit naturally in this environment and you follow them easily. This will then result in <strong>benefits for your business on the long term</strong>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2011/08/continuous-deployment-changes-your-mind/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Continuous Delivery Slides</title>
		<link>http://www.joergm.com/2011/07/continuous-delivery-slides/</link>
		<comments>http://www.joergm.com/2011/07/continuous-delivery-slides/#comments</comments>
		<pubDate>Tue, 05 Jul 2011 09:42:18 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[agile]]></category>
		<category><![CDATA[continuous delivery]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[version control]]></category>
		<category><![CDATA[cd]]></category>
		<category><![CDATA[event]]></category>
		<category><![CDATA[jug]]></category>

		<guid isPermaLink="false">http://www.joergm.com/?p=435</guid>
		<description><![CDATA[The last Java User Group event in Berlin was hosted at Hypoport. It was about Continuous Delivery. We had about 100 guests. There where two talks. One by Axel Fontaine who introduced Continuous Delivery especially in a Java environment. You can find his talk on Parleys or on his Blog. I had the pleasure to [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2011%2F07%2Fcontinuous-delivery-slides%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2011%2F07%2Fcontinuous-delivery-slides%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>The last <a href="http://www.jug-bb.de/">Java User Group</a> event in Berlin was hosted at <strong>Hypoport</strong>. It was about Continuous Delivery. We had about 100 guests.</p>
<p><a href="http://www.joergm.com/wp-content/uploads/2011/07/Jug_Gaeste1.jpg"><img class="aligncenter size-full wp-image-472" title="JUG BB" src="http://www.joergm.com/wp-content/uploads/2011/07/Jug_Gaeste1.jpg" alt="" width="640" height="427" /></a></p>
<p>There where<strong> two talks</strong>. One by <a href="http://twitter.com/#!/axelfontaine">Axel Fontaine</a> who introduced Continuous Delivery especially in a Java environment. You can find his talk on <a href="http://parleys.com/#id=2443&amp;sl=0&amp;st=5">Parleys</a> or on his <a href="http://www.axelfontaine.com/">Blog</a>.</p>
<p>I had the pleasure to introduce <strong>our experiences</strong> with Continuous Delivery. We are currently developing a new product. Since we started about a year ago we consequently used Continuous Delivery. We learned <strong>quite some lessons</strong> on our way which I presented that evening. My Slides are available <a href="http://www.slideshare.net/jug-berlin-brandenburg/continuous-delivery-in-der-praxis">here</a>. (As this was a german event the slides are in german)</p>
<p><a href="http://www.slideshare.net/jug-berlin-brandenburg/continuous-delivery-in-der-praxis"><img class="aligncenter size-full wp-image-467" title="Slide" src="http://www.joergm.com/wp-content/uploads/2011/07/CD_Agenda_Slide.png" alt="" width="450" height="276" /></a></p>
<p><strong>Thanks to everyone</strong> who attended the event. It was a really nice evening. Special thanks to everybody who helped organizing it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2011/07/continuous-delivery-slides/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pre-tested “Commits” using Git</title>
		<link>http://www.joergm.com/2011/05/pre-tested-commits-using-git/</link>
		<comments>http://www.joergm.com/2011/05/pre-tested-commits-using-git/#comments</comments>
		<pubDate>Sun, 29 May 2011 08:51:49 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[continuous delivery]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[version control]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[teamcity]]></category>
		<category><![CDATA[vcs]]></category>

		<guid isPermaLink="false">http://www.joergm.com/?p=378</guid>
		<description><![CDATA[The ability to use pre-tested commits is a feature of certain Continuous Integration servers like Teamcity. The whole concept is not easily transfered to a Git infrastructure. There are several approaches. Teamcity 6.5 now newly supports an approach called &#8220;Personal builds on branches&#8221; (see here). In our project we needed the feature a long time [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2011%2F05%2Fpre-tested-commits-using-git%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2011%2F05%2Fpre-tested-commits-using-git%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>The ability to use <strong>pre-tested commits</strong> is a feature of certain Continuous Integration servers like <a href="http://www.jetbrains.com/teamcity/">Teamcity</a>. The whole concept is <strong>not easily transfered to a Git</strong> infrastructure. There are several approaches. Teamcity 6.5 now newly supports an approach called &#8220;Personal builds on branches&#8221; (<a title="see here" href="http://www.jetbrains.com/teamcity/whatsnew/" target="_blank">see here</a>). In our project we needed the feature a long time ago and created a <strong>Git workflow that fulfills the intention</strong> of pre-tested commits <strong>and does not need any special features</strong> of the CI server.</p>
<p>But first of all what is the problem that is solved by testing a commit before it is committed? I think <a href="http://geekandpoke.typepad.com/geekandpoke/2010/06/real-coders-help-each-other.html">Geek and Poke</a> gets it perfectly. You want to be able to get the <strong>latest checkin</strong> from VCS an <strong>be sure that it builds</strong>. Classic CI is in the wrong sequence. You commit first and let the CI server test afterwards. Of course you recognize a problem fast but by then your fellow coders will already get your mess. The responsible coder will run the test on his machine first but what do you have a CI server for?</p>
<p>The solution is to let the CI server test your changes before they are available to other developers. The <strong>classic approach</strong> used by Teamcity is <strong>pretty complex</strong>. They use an IDE Plugin or a so called Command Line Runner. It works like this:</p>
<ol>
<li>Before you commit you will start the remote run using one of the tools. The tool will create a patch of your changes and send them to Teamcity.</li>
<li>Teamcity will now checkout a fresh version from the VCS and apply the patch to it.</li>
<li>Now your CI run will compile and test everything including your changes.</li>
<li>If successful the plugin will proceed to really check in your changes into Version Control.</li>
</ol>
<p>Aside from it&#8217;s complexity this solution <strong>did not work well with distributed VCS</strong> like Git or Mercurial.</p>
<p>With Version 6.5 there is another option &#8220;Personal builds on branches&#8221;. You commit your changes into special branches that follow a certain name pattern. If Teamcity recognizes this commit it will start a personal build and push to the master branch if the build was successful. A very <a title="similar approach" href="https://wiki.jenkins-ci.org/display/JENKINS/Designing+pre-tested+commit" target="_blank">similar approach</a> has been described for <a title="Jenkins" href="http://jenkins-ci.org/" target="_blank">Jenkins</a>.</p>
<p>We are using Git as our VCS since more than a year but the new solution by Teamcity has only been added very recently. This situation <strong>forced us to create our own solution</strong> and to our surprise this was much <strong>easier than expected</strong>. The main reason was the distributed nature of Git. Some of the points are:</p>
<ul>
<li>A commit is something that only effects your local repository as long as you don&#8217;t push it. This allows to test after a commit and before push. So you don&#8217;t need a special mechanism to create patches and send them somewhere.</li>
<li>The central repository is not the only one. Beside your local copy you can create as many repositories as you like. So you can push wherever you like to in order to e.g. run tests.</li>
<li>The central repository that you pull from doesn&#8217;t need to be the same that you push to.</li>
<li>Commits have a globally unique identifier. You can try to push a commit twice. Git will recognize it and don&#8217;t apply it the second time.</li>
</ul>
<p>You can probably already guess what I am up to, so lets show a picture of the overall setup.</p>
<p><a href="http://www.joergm.com/wp-content/uploads/2011/05/pre-tested-commits1.png"><img class="aligncenter size-full wp-image-444" title="pre-tested-commits" src="http://www.joergm.com/wp-content/uploads/2011/05/pre-tested-commits1.png" alt="" width="580" height="386" /></a></p>
<p>There is <strong>one central Git-repository </strong>that only <strong>contains pre-tested changes</strong>. I call this &#8220;Green Repository&#8221; because it should only contain changes that lead to green builds. Every developer pulls from this repository but <strong>nobody is allowed to push to it</strong>. Instead everybody has a personal repository (think fork if you were on <a title="GitHub" href="https://github.com/" target="_blank">GitHub</a>). The CI Server watches those personal repositories. After a commit it starts the compile and test. If that was successful it pushes the changes to the Green Repository. Now everybody can<strong> pull your changes</strong> and can <strong>be sure they have been tested</strong>.</p>
<p>You might wonder about some details of this setup so I try to answer some questions here:</p>
<ul>
<li>The remote server that contains the Green Repository and all personal remote repositories could be a simple <a title="git ssh setup" href="http://progit.org/book/ch4-2.html" target="_blank">git ssh setup</a>. We are using a local installation of the <a title="Gitorious" href="http://gitorious.org/" target="_blank">Gitorious</a> software instead. It is very easy to clone a central repository and to set access rights this way. There is also a commercial solution by the creators of GitHub called <a href="http://fi.github.com/" target="_blank">GitHub:FI</a>.</li>
<li>The remote-run on the CI Server needs to include 2 steps. Running the build (e.g. maven) and pushing the changes after successful build. We are using build dependencies in Teamcity in order to do these two steps. The first step is a simple maven goal and the second step is a simple command line call &#8220;git push&#8221;.</li>
<li>In order to make the push to your personal remote repository easier you should create an alias. &#8220;git remote add remote-run [your remote repo url]&#8221; then it is easy to push your changes using &#8220;git push remote-run&#8221;.</li>
<li>This solution works best with small teams that do not change often. The setup procedure for a new team member requires good knowledge of the solution. The setup itself can be done in less than 15 Minutes.</li>
</ul>
<p>The question is whether we will continue using our own solution or switch to the new feature of Teamcity. So far I can&#8217;t see any advantage of the Teamcity feature. With <strong>our solution</strong> we are <strong>even more flexible</strong> in regard of branch design. So I think our layout will live on for a while.</p>
<p>If your CI-Server has no support for pre-tested commits you might <strong>give our setup a try</strong>. I am eager to hear your experiences. I am also happy to answer any specific questions about the setup in comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2011/05/pre-tested-commits-using-git/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Learn your damn vocabulary!</title>
		<link>http://www.joergm.com/2011/01/learn-your-damn-vocabulary/</link>
		<comments>http://www.joergm.com/2011/01/learn-your-damn-vocabulary/#comments</comments>
		<pubDate>Sat, 29 Jan 2011 12:29:51 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[agile]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[improvement]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[metaphor]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.joergm.com/?p=415</guid>
		<description><![CDATA[Yesterday in a conversation with a team-mate we had the idea of a metaphor that turned out to be very useful. Learning programming has a lot in common with learning a foreign language. We were talking about different experiences while programming. Sometimes you are in a real flow. You can just fluently express all your [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2011%2F01%2Flearn-your-damn-vocabulary%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2011%2F01%2Flearn-your-damn-vocabulary%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Yesterday in a conversation with a team-mate we had the idea of a metaphor that turned out to be very useful. <strong>Learning programming </strong>has a lot in common with<strong> learning a foreign language</strong>.</p>
<p>We were talking about different experiences while programming. Sometimes you are in a real flow. You can just <strong>fluently</strong> express all your ideas and create <strong>hundreds of lines without stopping</strong>. Other times you need to <strong>stop every second line</strong> to google some details or ask other people.</p>
<p>When using foreign languages you can find situations that feel exactly the same. The <strong>tourist with a dictionary</strong> needs to lookup every second word. There is no way to start a real conversation. It&#8217;s only enough to get to the next train station. But after some years of learning he might join the natives and <strong>enjoy a conversation</strong>. He can talk fluently and does not look up words or think about the grammar.</p>
<p>If the situations feel so similar, what can we learn from the metaphor. We should look what it takes to become a fluent speaker in a foreign language:</p>
<ul>
<li>Learning vocabulary</li>
<li>Learning grammar</li>
<li>Using the language</li>
</ul>
<p><strong> Vocabulary</strong> in the world of programming is similar to basic language constructs, keywords and knowing what functionality your libraries are offering. I would also include knowledge about the editor or IDE, keyboard shortcuts and version control.<br />
So what do you need to do to get fluent in your language. <strong>Learn your damn vocabulary!</strong> You really need to <strong>memorize it</strong>. It is not enough to be able to look it up. This would be like looking up every second word in a dictionary. A fluent conversation is impossible. Now the good news is, that in a natural language about 1000 words are enough to conduct a fluent conversation. Something similar is probably true for programming. You don&#8217;t need to know every detail to be fluent.<br />
But the guy with a vocabulary of 1000 words will probably never win a Pulitzer prize. A lot of people think if they know the basics of their programming environment it is sufficient. <strong>No!</strong> You have to constantly<strong> extend your vocabulary</strong>. I am often surprised by discovering new features of the JDK, my IDE or the libraries we are using. Often I realize that I could have saved a lot of time, if only I did know this before. So go and discover new vocabulary and don&#8217;t forget to memorize it.</p>
<p><strong>Grammar</strong> is more equivalent to<strong> higher level constructs</strong> like design patterns, data structures or algorithms. When you learn a foreign language, grammar is very helpful in understanding the right way to combine the words. If you don&#8217;t know the grammar, the way you use the language usually sounds funny to native speakers. The same goes for the grammar of programming. So learn it if you don&#8217;t want to sound funny.<br />
There is another interesting effect. A fluent user of a language usually does not think about grammar. He can often not even explain why he used the words in a certain way. It just felt right. There is a lesson in it. Learn your grammar well but after a while <strong>don&#8217;t try to think about it to much</strong> in order to talk fluently.</p>
<p>Last but not least in order to get fluent in a language you have to <strong>use it</strong>. You usually start in a class together with a teacher. You have a save environment where you can try your vocabulary and grammar without fear. A good way to do this for programming are <a title="code katas" href="http://codekata.pragprog.com/">code katas</a>. You are in a save environment with peers that support you and give you feedback. You have to <strong>repeat</strong> a kata often <strong>to memorize </strong>every important vocabulary.<br />
There are many other well known ways to use programming in order to get fluent:</p>
<ul>
<li>Read other peoples code</li>
<li>Do private projects (and open source them to get feedback)</li>
<li>And of course your do your daily business</li>
</ul>
<p>Like learning a foreign language, learning programming takes many years. In the beginning you will be like the tourist and his dictionary. Just make sure that you <strong>don&#8217;t stay the tourist</strong>.</p>
<p>Next time you are stuck every second line while programming try to identify what vocabulary you just did not memorize or what grammar you probably not understood. Then memorize it and repeat &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2011/01/learn-your-damn-vocabulary/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Executing shell commands in Groovy</title>
		<link>http://www.joergm.com/2010/09/executing-shell-commands-in-groovy/</link>
		<comments>http://www.joergm.com/2010/09/executing-shell-commands-in-groovy/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 05:48:00 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[groovy]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://www.joergm.com/?p=375</guid>
		<description><![CDATA[Groovy is a good alternative to classic shell scripting for the Java experienced developer. I already wrote about this here. A common scenario is to call other shell commands from your scripts. Groovy makes this easy, but during a recent project I learned about some pitfalls. I will explain them here and also how to [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2010%2F09%2Fexecuting-shell-commands-in-groovy%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2010%2F09%2Fexecuting-shell-commands-in-groovy%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Groovy is a good alternative to classic shell scripting for the Java experienced developer. I already wrote about this <a href="http://www.joergm.com/2009/12/scripting-magic-with-groovy-grape-and-jetty/">here.</a> A common scenario is to call other shell commands from your scripts. Groovy makes this easy, but during a recent project I learned about some pitfalls. I will explain them here and also how to avoid them.</p>
<p><strong>The simple way</strong></p>
<p>Executing a simple command is just a matter of putting an .execute() after a string like that:</p>
<pre class="brush: groovy; title: ; notranslate">
&quot;mkdir foo&quot;.execute()
</pre>
<p><em>(Please ignore the fact for now, that you could do this using the Java standard functionality. This would be more effective in this example. Believe me, there are more complex requirements where you definitely need to call a shell command. I just keep the examples simple.)</em></p>
<p><strong>Evaluating the exit value</strong></p>
<p>What if you want to know whether this action was successful? In a shell script you usually check the exit value. Thats still straightforward:</p>
<pre class="brush: groovy; title: ; notranslate">
def exitValue = &quot;mkdir foo&quot;.execute().exitValue()
if(!exitValue)
  //do your error-handling
</pre>
<p>&#8220;execute()&#8221; just creates a java.lang.Process object. This simply returns an int with the exit value when calling exitValue() which you can use in your script.</p>
<p><strong>Printing the output</strong></p>
<p>Let&#8217;s say you want to see the result of the shell command during the runtime of your script. The easy approach would be:</p>
<pre class="brush: groovy; title: ; notranslate">
println &quot;ls&quot;.execute().text
</pre>
<p>If you want to combine text output and evaluation of the exit value it starts getting less elegant:</p>
<pre class="brush: groovy; title: ; notranslate">
def process = &quot;ls&quot;.execute()
process.text.eachLine {println it}
if(!process.exitValue())
...
</pre>
<p>This works, but not very well. It has two major issues:</p>
<ul>
<li>The output will not happen until the shell command is finished. This is ok for a simple &#8220;ls&#8221; but will get ugly, when you have a long running command.</li>
<li>process.text contains only standard out by default, but not err out.</li>
</ul>
<p>To solve this you can&#8217;t use the simple &#8220;.execute()&#8221; anymore. You need to fall back to java.lang.ProcessBuilder. This allows you to &#8220;redirectErrorStream()&#8221; which joins both streams together as it would look like when executing the command on a shell. Here is the example code:</p>
<pre class="brush: groovy; title: ; notranslate">
  def process=new ProcessBuilder(&quot;ls&quot;).redirectErrorStream(true).start()
  process.inputStream.eachLine {println it}
</pre>
<p><strong>The working directory</strong></p>
<p>Another pitfall is the current working directory. In a simple shell script you would just &#8220;cd&#8221; into the new working directory and then continue with your script. This would not work in a groovy script. As groovy is using the underlying Java mechanisms the &#8220;cd&#8221; command has no effect to the following instances of Process. Instead you need to tell the ProcessBuilder where your working directory has to be. There are several ways to do this. The first would be to add a &#8220;directory(File)&#8221; call to the ProcessBuilder from the example above. This would look like that:</p>
<pre class="brush: groovy; title: ; notranslate">
  def processBuilder=new ProcessBuilder(&quot;ls&quot;)
  processBuilder.redirectErrorStream(true)
  processBuilder.directory(new File(&quot;Your Working dir&quot;))  // &lt;--
  def process = processBuilder.start()
  ...
</pre>
<p>Fortunately there is a more convenient way when you use the execute method. You can use an overloaded version with two parameters. The first is a String array or a List containing environment variables or null if you don&#8217;t need them. The second is the working directory in form of a File object. Here is a code example:</p>
<pre class="brush: groovy; title: ; notranslate">
   &quot;your command&quot;.execute(null, new File(&quot;your working dir&quot;))
</pre>
<p><em>As a side note, if you need to set specific environment variables you also need to set them for each call.  </em></p>
<p><strong>Using wildcard characters</strong></p>
<p>This pitfall is described in many Groovy books but this post would not be complete without it. Using Wildcards like in the following example would not work.</p>
<pre class="brush: groovy; title: ; notranslate">
   &quot;ls *.java&quot;.execute()
</pre>
<p>Instead of listing all Java source files in the current directory as you might expect, it will try to list a file called &#8220;*.java&#8221;. It is very unlikely that this file is found. Wildcards like * are interpreted by the shell. The execute command is not using one. You need to call the shell first and let it interpret the wildcard-characters. On OSX and Linux this is simply done by adding a &#8220;sh -c&#8221; in front of the command. Something slightly different applies on Windows which I leave you to look up. The following command will do the expected. </p>
<pre class="brush: groovy; title: ; notranslate">
   &quot;sh -c ls *.java&quot;.execute()
</pre>
<p>It doesn&#8217;t do any harm to add this prefix to all shell commands you like to start. You only need to take care of the operating system your script is running on. I am in the fortunate position to expect a UNIX-like shell on every computer in my project so I simply add &#8220;sh -c&#8221;. </p>
<p><strong>Putting it all together</strong></p>
<p>Because of all the issues mentioned above I ended up adding two methods to my Groovy scripts called executeOnShell. These methods solves the pitfalls mentioned and still result in  a concise syntax when calling shell commands from the script. </p>
<pre class="brush: groovy; title: ; notranslate">
def executeOnShell(String command) {
  return executeOnShell(command, new File(System.properties.'user.dir'))
}

private def executeOnShell(String command, File workingDir) {
  println command
  def process = new ProcessBuilder(addShellPrefix(command))
                                    .directory(workingDir)
                                    .redirectErrorStream(true)
                                    .start()
  process.inputStream.eachLine {println it}
  process.waitFor();
  return process.exitValue()
}

private def addShellPrefix(String command) {
  commandArray = new String[3]
  commandArray[0] = &quot;sh&quot;
  commandArray[1] = &quot;-c&quot;
  commandArray[2] = command
  return commandArray
}
</pre>
<p>The method executeOnShell is overloaded, so that you can either call it with a working directory or without. It also returns the exitValue, so you can easily evaluate it. This is of course not complete, as it does not include the ability to set Environment variables and it works only on a Unix-like shell. It is sufficient for my current use cases.<br />
Please feel free to use it and to add your own requirements. If you know of any other pitfalls when executing shell commands from Groovy please leave a comment.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2010/09/executing-shell-commands-in-groovy/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Ten years ago …</title>
		<link>http://www.joergm.com/2010/02/ten-years-ago/</link>
		<comments>http://www.joergm.com/2010/02/ten-years-ago/#comments</comments>
		<pubDate>Sun, 14 Feb 2010 11:08:09 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[history]]></category>
		<category><![CDATA[software development]]></category>

		<guid isPermaLink="false">http://www.joergm.com/?p=330</guid>
		<description><![CDATA[This is really a fun exercise.  Just try to remember the situation as it was ten years ago. You can do this for several topics, but as this is a technology blog I will focus on technology. Beside of fun it has some nice side effects like improving your long term memory or giving you [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2010%2F02%2Ften-years-ago%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2010%2F02%2Ften-years-ago%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>This is really a fun exercise.  Just try to remember the situation as it was ten years ago. You can do this for several topics, but as this is a technology blog I will focus on technology. Beside of fun it has some nice side effects like improving your long term memory or giving you a better feeling how fast things are really moving. That&#8217;s something which is easily missed if you only look at short term events. And if you forget this you might be surprised by things happening faster than you thought.</p>
<p>So here are my points. They are completely from my memory and not guaranteed to be accurate.  This will of course describe the situation where I lived, which was in Germany.</p>
<p>Ten years ago &#8230;</p>
<p><strong>Hardware</strong></p>
<ul>
<li>My<strong> </strong>private<strong> PC</strong> was a 233 Mhz Pentium with about 64 MB of Ram and a 6 GB HD. At this time it was already more than 2 years old. I think a good PC at this time would have had a 600 Mhz Pentium 2. It used Windows ME, which was still DOS based but the only possible choice if you wanted to occasionally play a game. I had a second partition with SUSE Linux, but just to experiment. Using it as the primary desktop OS would have been a masochistic experience.</li>
<li>My<strong> </strong>business<strong> Notebook</strong> was a Compaq  with something between 300 and 400 Mhz, a 13 inch Display and about 4 GB hard drive. That was pretty good at this time. Buying a notebook like this for private use was unlikely as they were priced at about 7000 Deutsche Mark (ca. 3500 Euro)  each. The <strong>Euro</strong> was not used 10 years ago, but price tags already had to include it.</li>
<li><strong>Apple</strong> started to become popular again. The iMac (the colored one with a CRT Screen) was the first Mac that was available in general electronic stores (like Media Markt) in Germany. It still used System 9. I thought it might be a nice toy for my girlfriend, but for serious computing?</li>
<li>Speaking of <strong>CRT</strong>. This was the dominant Display technology. A 17 inch display with a screen resolution of 1024 * 768 was the standard. The first 15 inch <strong>LCD</strong> Displays were available but they were ridiculous expensive and were only useful for showing static pictures. As soon as something started to move on the screen you did know you just burned money.</li>
</ul>
<p><strong>Internet</strong></p>
<ul>
<li>My <strong>Internet Connection</strong> at home was an ISDN line. (64 kBit up and down) This at least allowed to get a phone call, while browsing the net at the same time.</li>
<li>I think at about this time I ordered my first <strong>DSL</strong>. I had to wait more than one year to get it. Transfer rates of 768 kBit download  and 128 kBit upload were revolutionary at this time. Even more important was the <strong>flat rate</strong>, as you usually had to pay per minute.</li>
<li><strong>Google</strong> was the new kid on the block. Beside better search results it had a revolutionary interface. Just a search box and a logo. All other search engines (Altavista, Excite, Lycos …) tried to be portals to the internet including news, ads and much more. They sometimes took minutes to load on a dial-up connection.</li>
</ul>
<p><strong>Mobile technology</strong></p>
<ul>
<li><strong>Mobile Phones</strong> just started to become popular for the masses. Until then they were seen as status symbols. I had two phones at this time a Siemens S25 as company phone and a C25 as private. The S25 even had a color display (the only one on the market). It had stunning 4 colors.</li>
<li><strong>SMS</strong> just started too. People learnt how to use this strange 160 character message thing. It was priced 0.39 DM each. There are still phone providers today that charge 0.19 Euro, which is even a bit more expensive than 10 years ago.</li>
<li><strong>Mobile data transfer</strong> was only possible in GSM-dailup-mode which meant 9600 bit/s up- and download. The first GPRS-phones which allowed package oriented transfer and 48.000 bit/s download were available about a year later.</li>
<li><strong>Palm PDAs</strong> were wildly successful in Business. It was a status symbol to have one. The Palm V had a really nice design, but had a monochrome LCD Display. The latest invention was the Palm IIIc which was the first to have a color display (240*240 and 256 colors). I had one and the most annoying thing was that you could not read anything on this display when you were outside.</li>
</ul>
<p><strong>Consumer electronics</strong></p>
<ul>
<li>Most people used <strong>CD-Players</strong> for listening to music. Portable CD-Players were pretty common.</li>
<li>There were the first dedicated <strong>MP3</strong> Players. But they used Flash-RAM which was very expensive. A 64 Mbyte Compact Flash card did cost about 500 Deutsche Mark (ca. 300 Dollars) and did not store more music than a CD. That was not really a competition for CD-Players or even the classic Walkman.</li>
<li><strong>TVs</strong> were usually CRT. There were the first flatscreens based on plasma technology. But they were priced at the same range as a small car. A lot of the CRT TVs were already 16:9. But you needed several strong men to move one. Some of these monsters had more than 100 kg.</li>
</ul>
<p><strong>Software and Programming</strong></p>
<ul>
<li><strong>Java</strong> was a huge hype. It was used in a lot of places, especially on the server side. It was not very successful on the desktop. (Deja vu?) Java was also recognized as being very slow. Which is funny because today many people compare new programming languages like Groovy, Scala or even Ruby to Java as the benchmark.</li>
<li>Java already had some <strong>IDEs.</strong> I think the most prominent was the Borland JBuilder. Things like automated refactoring were still unknown.</li>
<li>There were some rumors about a strange thing called <strong>Extreme Programming</strong>. Those guys were supposed to call programming the most important thing when creating software. Scary!</li>
<li><strong>Open Sourc</strong><strong>e</strong> software was used in some companies. Especially as web servers. It was ok to use it for this unimportant piece of infrastructure. But using open source for some mission critical stuff would still have been a revolution.</li>
</ul>
<p>I could write on for hours but that&#8217;s probably enough for now. I hope you enjoyed reading this as much as I enjoyed writing. Please share your own memories about ten years ago in the comments or on your own blog!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2010/02/ten-years-ago/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Why all programmers should blog</title>
		<link>http://www.joergm.com/2010/01/why-all-programmers-should-blog/</link>
		<comments>http://www.joergm.com/2010/01/why-all-programmers-should-blog/#comments</comments>
		<pubDate>Sat, 30 Jan 2010 09:11:35 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[agile]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[clean code]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.brainoutprintln.com/?p=298</guid>
		<description><![CDATA[There are some obvious reasons why you should start blogging when you are a programmer. Most of them also apply to everybody else: You share your knowledge. This is a benefit for all of us. If everybody would be blogging about all the little issues they had then a Google-Search would help us even more. [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2010%2F01%2Fwhy-all-programmers-should-blog%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2010%2F01%2Fwhy-all-programmers-should-blog%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>There are some obvious reasons why you should start blogging when you are a programmer. Most of them also apply to everybody else:</p>
<ul>
<li>You share your knowledge. This is a benefit for all of us. If everybody would be blogging about all the little issues they had then a Google-Search would help us even more. I am sure nearly every problem in the world is already solved. It is just not written down.</li>
<li>It&#8217;s a kind of self marketing. A potential employer can get a much better picture of your abilities than he could from CVs or references. When I hire somebody it is already a huge plus for him when he has a blog at all.</li>
<li>Explaining things to other people is the best way to learn. You can only teach what you fully understand. This is at least as efficient as hands on experience.</li>
<li>You might even make some money with blogging. There are several sites about this. If you are interested look <a title="here" href="http://www.copyblogger.com/" target="_blank">here</a> or <a title="here" href="http://www.problogger.net/" target="_blank">here</a>.</li>
</ul>
<p>But the main reason is something else. Some years ago I read an article about software documentation. There was a lot of wisdom in it, but one phrase sticked to my brain:</p>
<p><em>Programming is doing something weird to your brain. When you write a piece of documentation right after a programming session the result is likely to be barely readable for human beings</em>.</p>
<p>If that&#8217;s true then the opposite should work too.  Blogging teaches you to write for people, which is exactly what you should do in your code. Good code needs to be easy to understand to be easy to maintain. There are whole books about this like the famous <a title="Clean Code" href="http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1264841558&amp;sr=8-1" target="_blank">Clean Code</a> by Uncle Bob.</p>
<p>I think blogging does something weird to your brain, that makes your code better readable for human beings. So:</p>
<p><strong>If you want to become a better programmer, start blogging!</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2010/01/why-all-programmers-should-blog/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Scripting magic with Groovy, Grape and Jetty</title>
		<link>http://www.joergm.com/2009/12/scripting-magic-with-groovy-grape-and-jetty/</link>
		<comments>http://www.joergm.com/2009/12/scripting-magic-with-groovy-grape-and-jetty/#comments</comments>
		<pubDate>Thu, 31 Dec 2009 15:56:29 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[groovy]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[Jetty]]></category>
		<category><![CDATA[Script]]></category>

		<guid isPermaLink="false">http://www.brainoutprintln.com/?p=276</guid>
		<description><![CDATA[Groovy 1.7 has just been release and it&#8217;s time to play again. One of the new features, Grape inspired me to the try the following. I created a script that acts as a simple webserver using embedded jetty without the need to install anything else than Groovy 1.7 on your computer. Just save the script [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2009%2F12%2Fscripting-magic-with-groovy-grape-and-jetty%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2009%2F12%2Fscripting-magic-with-groovy-grape-and-jetty%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Groovy 1.7 has just been release and it&#8217;s time to play again. One of the new features, <a href="http://groovy.codehaus.org/Grape">Grape</a> inspired me to the try the following. I created a script that acts as a simple webserver using embedded jetty without the need to install anything else than Groovy 1.7 on your computer. Just save the script as simpleWebServer, make it executable and start it like </p>
<pre class="brush: plain; title: ; notranslate">
./simpleWebServer -d someDirWithHTMLFiles -p 9000
</pre>
<p>Surf to http://localhost:9000 and you will see. </p>
<p>Here is the full script. I will explain the details further down.</p>
<pre class="brush: groovy; title: ; notranslate">
#!/usr/bin/env groovy

@Grab('org.mortbay.jetty:jetty:6.1.22')
import org.mortbay.jetty.*;
import org.mortbay.jetty.handler.*

def cli = new CliBuilder (usage:'simpleHtmlServer -p PORT -d DIRECTORY')
cli.with {
 h longOpt:'help', 'Usage information'
 p longOpt:'port',argName:'port', args:1, type:Number.class,'Default is 8080'
 d longOpt:'dir', argName:'directory', args:1, 'Default is .'
}

def opts = cli.parse(args)
if(!opts) return
if(opts.help) {
  cli.usage()
  return
}

def server = new Server(opts.port.toInteger()?:8080)
def resourceHandler = new ResourceHandler(welcomeFiles:[&quot;index.html&quot;],
                                         resourceBase:opts.dir?:&quot;.&quot;)
server.handler = new HandlerList(handlers:[resourceHandler, new DefaultHandler()])

server.start()
server.join()
</pre>
<p>Here are the magic details about the script:</p>
<p><strong>1. The Shebang</strong></p>
<p>The first important thing about this script is the shebang. </p>
<pre class="brush: groovy; title: ; notranslate">
#!/usr/bin/env groovy
</pre>
<p>If you are using a real operating system (sorry Windows users), this will let you start the script like a normal executable. I usually skip the .groovy appendix on script files, so it really feels like you are using a normal command line utility.</p>
<p><strong>2. Grape</strong></p>
<p>The next line uses the new feature of Groovy 1.7, called Grape. This is a dependency System that allows to load any dependency, that is available in the maven-repositories to be used inside a script.</p>
<pre class="brush: groovy; title: ; notranslate">@Grab('org.mortbay.jetty:jetty:6.1.22')</pre>
<p>The syntax is pretty easy. It uses the maven notation: groupId:artifactId:version. There is an alternative version that uses separate attributes for each but I prefer the shortcut.<br />
This line will lookup the dependency in the maven repository, download it and store it in ~/.groovy/grape. So the first start of the script might take a moment. The second time will be faster.<br />
Grape allows to use the full java ecosystem in a simple groovy script without any additional install. Groovy 1.7 is enough. I think this makes scripting in groovy incredible powerful.</p>
<p><strong>3. The CliBuilder</strong><br />
The script should really feel like a command line utility. Therefore it needs to deal with parameters. This is where the CliBuilder comes in. </p>
<pre class="brush: groovy; title: ; notranslate">
def cli = new CliBuilder (usage:'simpleHtmlServer -p PORT -d DIRECTORY')
cli.with {
 h longOpt:'help', 'Usage information'
 p longOpt:'port',argName:'port', args:1, type:Number.class,'Default is 8080'
 d longOpt:'dir', argName:'directory', args:1, 'Default is .'
}

def opts = cli.parse(args)
if(!opts) return
if(opts.help) {
  cli.usage()
  return
}
</pre>
<p>Groovy includes Apache commons CLI. But where the Java version is already helpful in parsing parameters, the Groovy version gets really simple. The example above creates one CliBuilder, that provides a &#8220;DSL&#8221; for defining the parameters. Further down they are three parameters defined. This is all thats needed.<br />
After the args are parsed we can just simply use them using Groovy properties syntax like opts.parameterName. Even a pretty usage statement can be printed, when &#8211;help is called.</p>
<p><strong>4. Dynamic constructors</strong><br />
I used one of the embedded Jetty examples (FileServer.java) as the foundation of my script. The configuration of the handlers looked something like that in Java:</p>
<pre class="brush: java; title: ; notranslate">
ResourceHandler resource_handler=new ResourceHandler();
resource_handler.setWelcomeFiles(new String[]{&quot;index.html&quot;});
resource_handler.setResourceBase(args.length==2?args[1]:&quot;.&quot;);

HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{resource_handler,new DefaultHandler()});
</pre>
<p>Thats pretty long. Now the Groovy version looks like that:</p>
<pre class="brush: groovy; title: ; notranslate">
def resourceHandler = new ResourceHandler(welcomeFiles:[&quot;index.html&quot;],
                                          resourceBase:opts.dir?:&quot;.&quot;)
server.handler = new HandlerList(handlers:[resourceHandler, new DefaultHandler()])
</pre>
<p>It uses dynamic constructors. Groovy allows to call a virtual constructor with a map of arguments, where the elements are actually bean properties. This allows a much more concise construction of an object, even if the original creator wasn&#8217;t so kind to provide a convenience constructor.</p>
<p><strong>5. The Elvis Operator</strong></p>
<p>You probably wondered what the following statement did in the last example:</p>
<pre class="brush: plain; title: ; notranslate">
opts.dir?:&quot;.&quot;
</pre>
<p>Well, that was Elvis. In Java there is the ternary operator, which goes like this:</p>
<pre class="brush: plain; title: ; notranslate">
(condition)?(result if true):(result if false)
</pre>
<p>In Grovvy there is something called the Groovy truth, which says if a statement is null, then it is false, else it is true. This makes the Elvis operator possible. Elvis says, if the statement is true (as in Groovy truth) then use the value of the statement, else use the value after the colon.  This is a very concise way for realizing default values, which is often needed in scripts</p>
<p>With all the scripting features that were added in earlier versions and with Grape in 1.7 I think Groovy is finally a great alternative to usual scripting languages. When you are experienced in Java it&#8217;s probably much simpler to write a script in Groovy than in Perl, Ruby or even Bash. For me this is definitely true.</p>
<p>Well done, Groovy team! </p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2009/12/scripting-magic-with-groovy-grape-and-jetty/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>IntelliJ IDEAs new directory-based project format</title>
		<link>http://www.joergm.com/2009/10/intellij-ideas-new-directory-based-project-format/</link>
		<comments>http://www.joergm.com/2009/10/intellij-ideas-new-directory-based-project-format/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 09:21:42 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[intellij idea]]></category>

		<guid isPermaLink="false">http://www.brainoutprintln.com/?p=265</guid>
		<description><![CDATA[I am currently playing with the EAP-Version (Early Access Program) of my favorite IDE IntelliJ IDEA. Since the new version is not that far away it is time to learn the new features and I discovered one that surprised me. A small but pretty nice change. (Update: Thanks to Strug I have realized that this [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2009%2F10%2Fintellij-ideas-new-directory-based-project-format%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2009%2F10%2Fintellij-ideas-new-directory-based-project-format%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I am currently playing with the EAP-Version (Early Access Program) of my favorite IDE  IntelliJ IDEA. Since the new version is not that far away it is time to learn the new features and I discovered one that surprised me. A small but pretty nice change.</p>
<p>(<strong>Update: </strong>Thanks to Strug I have realized that this feature is already present in Idea 8, you can use the action &#8220;Open in New (Directory based) format&#8221; to convert your project. Fortunately they renamed it to &#8220;Save as Directory-Based Format …&#8221; in Maia. )</p>
<p>IDEA has a new format to store the project files. It is called directory-based. Instead of using the three famous files <em>.ipr .iml</em> and <em>.iws</em> IDEA will now store all information into a directory, which is simply called <em>.idea</em>. It is located in the root folder of the project. This seems to be somewhat similar to eclipse&#8217;s .project folder. In a small example project I created the content of the new directory looks like this:</p>
<pre>-rw-r--r--  1 joerg  joerg    163 17 Okt 09:53 ant.xml
-rw-r--r--  1 joerg  joerg   2107 17 Okt 09:53 compiler.xml
drwxr-xr-x  3 joerg  joerg    102 17 Okt 09:53 copyright
drwxr-xr-x  3 joerg  joerg    102 17 Okt 09:53 dictionaries
-rw-r--r--  1 joerg  joerg    277 17 Okt 09:53 encodings.xml
-rw-r--r--  1 joerg  joerg    170 17 Okt 09:53 fileColors.xml
-rw-r--r--  1 joerg  joerg   1595 17 Okt 09:53 misc.xml
-rw-r--r--  1 joerg  joerg    258 17 Okt 09:53 modules.xml
-rw-r--r--  1 joerg  joerg    207 17 Okt 09:53 templateLanguages.xml
-rw-r--r--  1 joerg  joerg    169 17 Okt 09:53 vcs.xml
-rw-r--r--  1 joerg  joerg  38245 17 Okt 10:21 workspace.xml</pre>
<p>The files included in this directory depend on the settings you change in the IDE. So, if you would for instance set the SQL dialect for your project there will be another file called sqldialects.xml containing all settings about this.</p>
<p>There is one special file in there, which is workspace.xml. This file contains individual settings for the workspace, which are definitely not intended to be shared via version control. This is equivalent to the .iws file of the old format. IDEA will put this file automatically on the ignore list of your version control.</p>
<p>I see some advantages of the new format.</p>
<ul>
<li>First of all it is easier to find specific settings. The filenames are meaningful and the files are small.</li>
<li>The new structure allows a very detailed control of which settings you want to share with your colleagues. If you don&#8217;t want to share e.g. your file coloring (another new feature of Maia) just put the file on the ignore list.</li>
<li>Directories of the projects saved in the new format will be recognized as projects in the open-project dialog. In the past this was one annoying additional click as you had to choose the .ipr file before.</li>
</ul>
<p>The new directory based format is a small change but a very good one. It is often a sum of little detail-improvements that save a lot of trouble in daily work. So I am looking forward to the other details to be discovered.</p>
<p>By the way JetBrains released an open source version of IDEA two days ago. So if you want to try this just go to <a title="jetbrains.org" href="http://www.jetbrains.org" target="_blank">www.jetbrains.org</a> and download the Community Edition.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2009/10/intellij-ideas-new-directory-based-project-format/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>A poor man’s countdown</title>
		<link>http://www.joergm.com/2009/08/a-poor-mans-countdown/</link>
		<comments>http://www.joergm.com/2009/08/a-poor-mans-countdown/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 21:13:45 +0000</pubDate>
		<dc:creator>Joerg</dc:creator>
				<category><![CDATA[agile]]></category>
		<category><![CDATA[scrum]]></category>
		<category><![CDATA[countdown]]></category>
		<category><![CDATA[low-tech]]></category>

		<guid isPermaLink="false">http://www.brainoutprintln.com/?p=224</guid>
		<description><![CDATA[We all know those high-tech solutions that show the time left to a certain event. There are huge LED-Displays, Dashboard-Widgets or even iPhone apps. For an upcoming release of our software a colleague installed a very low-tech version. You just need: a tape measure scissors a wall (a glass wall in our case) and something [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.joergm.com%2F2009%2F08%2Fa-poor-mans-countdown%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.joergm.com%2F2009%2F08%2Fa-poor-mans-countdown%2F&amp;source=JoergM&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>
We all know those high-tech solutions that show the time left to a certain event. There are huge LED-Displays,  Dashboard-Widgets or even iPhone apps.
</p>
<table>
<tr>
<td>
<img src="http://www.brainoutprintln.com/wp-content/uploads/2009/08/countdown.jpg" alt="countdown" title="countdown" width="250" height="300" class="alignnone size-full wp-image-225" />
</td>
<td valign="top" style="padding-left:10px;">
For an upcoming release of our software a colleague installed a very low-tech version.<br />
</br><br />
You just need:</p>
<ul>
<li>a tape measure</li>
<li>scissors</li>
<li>a wall (a glass wall in our case)</li>
<li>and something to attach the tape measure to the wall (some Scotch tape or Blue Tack will do)</li>
</ul>
<p>Attach the tape measure to the wall and cut a centimeter off each day. <strong>That&#8217;s it.</strong>
</td>
</tr>
</table>
<p>
It should not be a problem to raise the budget for this solution. Most of the stuff will be around in any office. A tape measure can often be found in furniture stores for free, although a plastic tape measure for a few cents usually looks much better.<br />
I love this kind of low-tech solutions. It&#8217;s a nice contrast to the high-tech around and even marketing can understand it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.joergm.com/2009/08/a-poor-mans-countdown/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

