<?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-6189016616585694043</id><updated>2011-11-27T16:51:16.561+01:00</updated><category term='WebApp'/><category term='Checkstyle'/><category term='BestPractices'/><category term='JBoss'/><category term='Performance'/><category term='Cargo'/><category term='OSGi'/><category term='QA'/><category term='Windows'/><category term='Java'/><category term='Google'/><category term='Profiles'/><category term='Testing'/><category term='Nexus'/><category term='Jenkins'/><category term='Maven'/><category term='Eclipse'/><category term='Tools'/><category term='Hudson'/><category term='Spring'/><category term='JUnit'/><category term='JEE'/><category term='Size'/><category term='oAW'/><category term='Optimization'/><title type='text'>Java Moods</title><subtitle type='html'>Java, Maven, Tools and everything else...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>46</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-4374742888575438552</id><published>2011-05-05T23:46:00.007+02:00</published><updated>2011-05-06T01:10:11.978+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jenkins'/><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>The Butler Dispute, Round 2</title><content type='html'>&lt;p&gt;Nearly 4 month have passed by since the renaming of Hudson project to Jenkins, which marks the climax of the &lt;a href="http://javamoods.blogspot.com/2011/02/butler-dispute.html"&gt;dispute&lt;/a&gt; between the old Hudson developers and the guys from Oracle and Sonatype.&lt;/p&gt;&lt;p&gt;Jenkins has made a great job since then, delivering 15 releases in a weekly schedule. Build number &lt;a href="http://kohsuke.org/2011/03/13/jenkins-hits-1-400/"&gt;1.400 was hit&lt;/a&gt; in March, wich is not a particular significant release but shows how well things go on. &lt;a href="http://javamoods.blogspot.com/2011/03/way-from-hudson-to-jenkins.html"&gt;The way from Hudson to Jenkins&lt;/a&gt; is as easy as it could be, and it seems like many users are going it. &lt;/p&gt;&lt;p&gt;Indeed there are a lot of reasons why to choose Jenkins over Hudson, just to name a few:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Support by the fabulous Hudson core development team &amp;ndash; with Kohsuke Kawaguchi, the creator of Hudson, and other brave guys.&lt;/li&gt;&lt;li&gt;Strong community activity  &amp;ndash; measured in figures like commit counts and mailing list traffic, see &lt;a href="http://bobbickel.blogspot.com/2011/03/jenkins-vs-hudson-time-to-upgrade.html"&gt;this post&lt;/a&gt; for some numbers.&lt;/li&gt;&lt;li&gt;Most of the plugins moved over to Jenkins &amp;ndash; 5 of the top 5 and 19 of the top 25 plugins continue primary development with Jenkins, see &lt;a href="http://jieryn.livejournal.com/4362.html"&gt;here&lt;/a&gt; for some statistics.&lt;/li&gt;&lt;li&gt;High quality and regular releases &amp;ndash; the weekly schedule led to 15 high quality releases, each of them providing a couple of bug fixes and new features (see &lt;a href="http://jenkins-ci.org/changelog"&gt;changelog&lt;/a&gt;). Moreover, a few weeks ago, Jenkins governance board &lt;a href="https://wiki.jenkins-ci.org/pages/viewpage.action?pageId=57180302"&gt;proposed to start another release line&lt;/a&gt; for most stable baselines with a 3-months schedule.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Even the Hudson board seems to have observed that Jenkins outperforms Hudson in many ways, at least they are thinking about "how to make it more attractive for plug-in developers to support both Hudson and Jenkins" (see &lt;a href="http://java.net/projects/hudson/lists/dev/archive/2011-05/message/18"&gt;this message&lt;/a&gt; on Hudson-Dev list). The author's perception is that "Hudson also appears to be slowing down development wise" and "another place where Hudson appears to be slowing down, is when you compare changelogs". Some of the ideas deal with copying approaches that are working fine for the Jenkins project.&lt;/p&gt;&lt;p&gt;Hence, it seems Jenkins is the winner of the battle and has in fact benefited from the fork.... until today.&lt;/p&gt;&lt;p&gt;Because today, &lt;a href="http://www.oracle.com/us/corporate/press/393483"&gt;Oracle submitted&lt;/a&gt; a proposal to move Hudson to the Eclipse Foundation. This is, well, somewhat astonishing since that means Oracle will lose both control and the Hudson trademarks &amp;ndash; which was the main background of the original dispute with the community.&lt;/p&gt;&lt;p&gt;As part of the proposal, other big players have announced support for the project, including IBM, VMware, Tasktop and Intuit. That means, moving the Hudson project to Eclipse will for sure result in higher attention and more resources (developers).&lt;/p&gt;&lt;p&gt;Does this change anything? Will Jenkins be the unlucky loser, after all? I don't think so. The heavens didn't really smile on Hudson since the fork (kind of bad karma) and I don't see why the move to Eclipse should change that. It's all about people, not code.&lt;/p&gt;&lt;p&gt;Moreover, Jenkins has been &lt;a href="http://www.sonatype.com/people/2011/05/sonatype-supports-hudsons-move-to-the-eclipse-foundation/"&gt;invited by Sonatype&lt;/a&gt; to reunite with Hudson. But... why should they do that? Jenkins is a vibrant project today, so what is the benefit? Also, there have been some deep disappointments on personal level that are not forgotten yet.&lt;/p&gt;&lt;p&gt;It's going to be interesting!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-4374742888575438552?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/4374742888575438552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2011/05/butler-dispute-round-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4374742888575438552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4374742888575438552'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2011/05/butler-dispute-round-2.html' title='The Butler Dispute, Round 2'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-4872846086524945163</id><published>2011-04-07T15:07:00.005+02:00</published><updated>2011-04-07T15:54:43.598+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QA'/><category scheme='http://www.blogger.com/atom/ns#' term='Jenkins'/><category scheme='http://www.blogger.com/atom/ns#' term='Checkstyle'/><title type='text'>Jenkins: Pimp It Up!</title><content type='html'>&lt;p&gt;Some days ago, I started to review what plugins are available for Jenkins, &lt;a href="http://javamoods.blogspot.com/2011/03/way-from-hudson-to-jenkins.html"&gt;my favorite CI server&lt;/a&gt;. I haven't done so for a long time, so I was somewhat surprised to see a full universe of plugins (380+) listed in the &lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Plugins"&gt;Wiki&lt;/a&gt;...&lt;/p&gt;&lt;p&gt;There is next to everything you can imagine. Among the plugins I would like to suggest for consideration are these:&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Dependency+Graph+View+Plugin"&gt;Dependency Graph View Plugin&lt;/a&gt; &amp;ndash; Shows the dependency graph of the Jenkins projects using graphviz. This greatly helps to keep track of dependencies between all your Jobs.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-TdG2Mq9kJEA/TZ3ACjfgHcI/AAAAAAAAADw/49Zj6msai9k/s1600/Jenkins_DependencyGraph.gif"&gt;&lt;img style="margin-left:50px; cursor:pointer; cursor:hand;width: 400px; height: 161px;" src="http://2.bp.blogspot.com/-TdG2Mq9kJEA/TZ3ACjfgHcI/AAAAAAAAADw/49Zj6msai9k/s400/Jenkins_DependencyGraph.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5592837462383664578" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Disk+Usage+Plugin"&gt;Disk Usage Plugin&lt;/a&gt; &amp;ndash; This plugin calculates and records disk usage (space for builds and workspace) per project and per build, and can display trend graphs.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-gYjzbit_khk/TZ3ACyGNk0I/AAAAAAAAAD4/XSyIrJ7wwMg/s1600/Jenkins_DiskUsage.gif"&gt;&lt;img style="margin-left:50px; cursor:pointer; cursor:hand;width: 400px; height: 168px;" src="http://4.bp.blogspot.com/-gYjzbit_khk/TZ3ACyGNk0I/AAAAAAAAAD4/XSyIrJ7wwMg/s400/Jenkins_DiskUsage.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5592837466304123714" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Global+Build+Stats+Plugin"&gt;Global Build Stats Plugin&lt;/a&gt; &amp;ndash; can be used to gather and display global build result statistics, monitoring over time, and show nice graphics.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-ZpxEKqoBVGU/TZ3ADAtgueI/AAAAAAAAAEA/K5LPUi06OK8/s1600/Jenkins_GlobalBuildStats.gif"&gt;&lt;img style="margin-left:50px; cursor:pointer; cursor:hand;width: 400px; height: 245px;" src="http://4.bp.blogspot.com/-ZpxEKqoBVGU/TZ3ADAtgueI/AAAAAAAAAEA/K5LPUi06OK8/s400/Jenkins_GlobalBuildStats.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5592837470227053026" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;And, of course, all the static analyzing plugins that scan result files of several static code analysis tools and visualize the results as trend graphs:&lt;ul&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Checkstyle+Plugin"&gt;Checkstyle Plug-in&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin"&gt;Cobertura Plugin&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/FindBugs+Plugin"&gt;FindBugs Plugin&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/JavaNCSS+Plugin"&gt;JavaNCSS Plugin&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/PMD+Plugin"&gt;PMD Plugin&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Task+Scanner+Plugin"&gt;Task Scanner Plugin&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Warnings+Plugin"&gt;Warnings Plugin&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-z3JagrhSN2k/TZ3ADLtjdDI/AAAAAAAAAEI/VOidk6R1ZOU/s1600/Jenkins_StaticAnalysis.gif"&gt;&lt;img style="margin-left:50px; cursor:pointer; cursor:hand;width: 400px; height: 223px;" src="http://3.bp.blogspot.com/-z3JagrhSN2k/TZ3ADLtjdDI/AAAAAAAAAEI/VOidk6R1ZOU/s400/Jenkins_StaticAnalysis.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5592837473180021810" /&gt;&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;Have fun!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-4872846086524945163?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/4872846086524945163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2011/04/jenkins-pimp-it-up.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4872846086524945163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4872846086524945163'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2011/04/jenkins-pimp-it-up.html' title='Jenkins: Pimp It Up!'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-TdG2Mq9kJEA/TZ3ACjfgHcI/AAAAAAAAADw/49Zj6msai9k/s72-c/Jenkins_DependencyGraph.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-7114992681247191691</id><published>2011-03-29T09:07:00.002+02:00</published><updated>2011-03-29T10:11:52.168+02:00</updated><title type='text'>DocBook with Maven Issue</title><content type='html'>&lt;p&gt;We are using &lt;a href="http://docbook.org/"&gt;DocBook&lt;/a&gt; for writing technical documentation for all our projects and in-house frameworks. We are actually quite happy with this approach, especially because we are able to automatically publish the docs in a number of formats, including HTML and PDF. To do so, we use the &lt;a href="http://docs.codehaus.org/display/MAVENUSER/Docbkx+Maven+Plugin"&gt;docbkx-maven-plugin&lt;/a&gt; in the project's nightly build.&lt;/p&gt;&lt;p&gt;So, all has been in best order... until I decided to upgrade this docbkx-maven-plugin from version 2.0.8 to current version 2.0.11 (due to some issues we had). After doing so, the document conversion issues an error which breaks the build:&lt;/p&gt;&lt;pre class="brush:xml"&gt;[ERROR] Failed to execute goal com.agilejava.docbkx:docbkx-maven-plugin:2.0.11:generate-pdf (pdf) on project builddoc-ma&lt;br /&gt;ven-plugin: Failed to transform to PDF: org.apache.fop.fo.ValidationException: null:30:723: Error(30/723): fo:table-body&lt;br /&gt; is missing child elements.&lt;br /&gt;[ERROR] Required Content Model: marker* (table-row+|table-cell+)&lt;/pre&gt;&lt;p&gt;Well, this is somewhat unexpected because I didn't change anything but the plugin version, and I don't see any reason it could not work as before. In particular, we are still using the same docbook version in our POM. Here is the relevant snippet:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;com.agilejava.docbkx&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;docbkx-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;2.0.11&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;dependencies&amp;gt;&lt;br /&gt;    &amp;lt;!-- the DocBook XML DTD and catalog files (see http://www.oasis-open.org/docbook) --&amp;gt;&lt;br /&gt;    &amp;lt;dependency&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;org.docbook&amp;lt;/groupId&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;docbook-xml&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;version&amp;gt;4.4&amp;lt;/version&amp;gt;&lt;br /&gt;      &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;&lt;br /&gt;    &amp;lt;/dependency&amp;gt;&lt;br /&gt;  &amp;lt;/dependencies&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;executions&amp;gt;&lt;br /&gt;    &amp;lt;execution&amp;gt;&lt;br /&gt;      &amp;lt;id&amp;gt;pdf&amp;lt;/id&amp;gt;&lt;br /&gt;      &amp;lt;goals&amp;gt;&lt;br /&gt;        &amp;lt;goal&amp;gt;generate-pdf&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;/goals&amp;gt;&lt;br /&gt;      &amp;lt;phase&amp;gt;post-site&amp;lt;/phase&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;        ...&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;    &amp;lt;/execution&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;  &amp;lt;/executions&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;configuration&amp;gt;&lt;br /&gt;    &amp;lt;htmlStylesheet&amp;gt;css/html.css&amp;lt;/htmlStylesheet&amp;gt;&lt;br /&gt;    &amp;lt;htmlCustomization&amp;gt;${basedir}/src/doc/xsl/html_chunk_customization.xsl&amp;lt;/htmlCustomization&amp;gt;&lt;br /&gt;    &amp;lt;foCustomization&amp;gt;${basedir}/src/doc/xsl/fopdf_customization.xsl&amp;lt;/foCustomization&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;  &amp;lt;/configuration&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;/pre&gt;&lt;p&gt;It's important to understand that we are using the &lt;a href="http://docbkx-tools.sourceforge.net/advanced.html"&gt;advanced customizing&lt;/a&gt; capabilities of DocBook, i.e. we customized the stylesheets used for rendering HTML and PDF. The created custom stylesheets contain an import to &lt;code&gt;urn:docbkx:stylesheet&lt;/code&gt;, and in the Maven POM the &lt;code&gt;htmlCustomization&lt;/code&gt; and &lt;code&gt;foCustomization&lt;/code&gt; properties point to those custom stylesheets. This is how it's supposed to be, and this is how it worked all along.&lt;/p&gt;&lt;p&gt;I found out that the error message is correct when building with plugin version greater than 2.0.8, since the &lt;code&gt;for-each&lt;/code&gt; element indeed does not return any element which results in an empty &lt;code&gt;fo:table-body&lt;/code&gt;. In fact, none of the &lt;code&gt;xsl:value-of&lt;/code&gt; in our customized stylesheet returned any value any more....&lt;/p&gt;&lt;p&gt;So here is why: since &lt;code&gt;docbkx-maven-plugin&lt;/code&gt; version 2.0.9, the plugin is using &lt;a href="http://docbook.xml-doc.org/snapshots/xsl-ns/README"&gt;namespaced stylesheets&lt;/a&gt;. That is, we must use a namespace in our custom stylesheet to be able to select any docbook element! See &lt;a href="http://groups.google.com/group/docbkx-tools-users/browse_thread/thread/af837b9c268f6b9b/01cc4eaef3ebaece?lnk=raot"&gt;this&lt;/a&gt; or &lt;a href="http://www.mail-archive.com/docbook-apps@lists.oasis-open.org/msg14755.html"&gt;this&lt;/a&gt; post for related comments.&lt;/p&gt;&lt;p&gt;Thus, all I have to do is to add the docbook namespace declaration at the top and add the docbook namespace prefix to all references to element names in my customization layer. See highlighted lines in this XSL snippet:&lt;/p&gt;&lt;pre class="brush:xml; highlight: [3,12]"&gt;&amp;lt;xsl:stylesheet xmlns:xsl=&amp;quot;http://www.w3.org/1999/XSL/Transform&amp;quot;&lt;br /&gt;                xmlns:fo=&amp;quot;http://www.w3.org/1999/XSL/Format&amp;quot;&lt;br /&gt;                xmlns:db=&amp;quot;http://docbook.org/ns/docbook&amp;quot;&lt;br /&gt;                exclude-result-prefixes=&amp;quot;date&amp;quot;&lt;br /&gt;                version=&amp;quot;1.0&amp;quot;&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;xsl:template name=&amp;quot;book.titlepage.separator&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;fo:block&amp;gt;&lt;br /&gt;      &amp;lt;fo:table table-layout=&amp;quot;fixed&amp;quot; width=&amp;quot;163mm&amp;quot;&amp;gt;&lt;br /&gt;        ...&lt;br /&gt;        &amp;lt;fo:table-body text-align=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;          &amp;lt;xsl:for-each select=&amp;quot;/db:book/db:bookinfo/db:revhistory/db:revision&amp;quot;&amp;gt;&lt;br /&gt;            ...&lt;br /&gt;          &amp;lt;/xsl:for-each&amp;gt;&lt;br /&gt;        &amp;lt;/fo:table-body&amp;gt;&lt;br /&gt;      &amp;lt;/fo:table&amp;gt;&lt;br /&gt;    &amp;lt;/fo:block&amp;gt;&lt;br /&gt;  &amp;lt;/xsl:template&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;&amp;lt;/xsl:stylesheet&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Well, that did the trick &amp;ndash; after spending a couple of hours of investigation... I think that issue should be clearly noted with the &lt;code&gt;docbkx-maven-plugin&lt;/code&gt; Maven plugin, because in the end it is an incompatability between versions 2.0.8 and 2.0.9. Alas, I did not find this information on the plugin's &lt;a href="http://docbkx-tools.sourceforge.net/docbkx-maven-plugin/changes-report.html"&gt;Changes Report&lt;/a&gt; page. At least, nothing that pointed me (not being a DocBook expert) into this direction...  :-(&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-7114992681247191691?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/7114992681247191691/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2011/03/docbook-with-maven-issue.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7114992681247191691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7114992681247191691'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2011/03/docbook-with-maven-issue.html' title='DocBook with Maven Issue'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-2413917405220025184</id><published>2011-03-21T20:08:00.006+01:00</published><updated>2011-03-21T21:17:48.665+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Jenkins'/><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>The Way From Hudson To Jenkins</title><content type='html'>&lt;p&gt;Some time has gone by since the &lt;a href="http://javamoods.blogspot.com/2011/02/butler-dispute.html"&gt;Hudson/Jenkins fork&lt;/a&gt;... and there has been even more talk in the community. However, slowly the dust settles, everybody is getting back to business. And finally, we decided to switch from Hudson to Jenkins! This is about why and how.&lt;/p&gt;&lt;h4&gt;Why move to Jenkins?&lt;/h4&gt;&lt;p&gt;But wait: who has forked, anyways? Is it Jenkins that forked Hudson, or is it Hudson that did the fork of Jenkins? There is some evidence that the community just did a rename of the project (due to trademark conflicts), and after that &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=317610"&gt;Oracle forked Jenkins&lt;/a&gt;, using the Hudson name they claim holding the trademark on.&lt;/p&gt;&lt;p&gt;You may think this question is a purely theoretical one, but actually it's not. I'll have to legitimate the decision to move to Jenkins to my stakeholders, and using a fork would be a "smell". Project forks are usually not as good as the "original", are possibly done out of selfish reasons, are considered to harm the community etc. Hence, not moving to a fork but instead following the "real" project is a good reason for the move to Jenkins.&lt;/p&gt;&lt;p&gt;An even better one is "project vibrancy", that is the pace of development and level of support provided by the community. This is usually measured by indicators such as the number of commits, the mailing list traffic, the quantity, quality and regularity of releases etc. See &lt;a href="http://daniel.gredler.net/2011/02/15/hudson-and-jenkins-two-weeks-later/"&gt;this post&lt;/a&gt; for such an analysis on commit counts and mailing lists post counts. This is more than four weeks old now and covers not more than two weeks, but nevertheless the result is obvious: Jenkins moves much faster than Hudson does, and community is much more agile. This is confirmed by following the dev mailing lists of both: for Hudson, most of the relevant posts are by either Oracle or Sonatype engineers &amp;ndash; seems the Hudson community has become pretty small... Moreover, as &lt;a href="http://jieryn.livejournal.com/4362.html"&gt;this post&lt;/a&gt; shows, most of the top plugins will continue primary development under Jenkins.&lt;/p&gt;&lt;p&gt;Last not least, I really respect Kohsuke Kawaguchi (the original creator of Hudson) and what he has done for us. I feel ashamed by how Oracle is dealing with him and the rest of the core team, that's why I have a strong tendency to follow the "good guys" with Jenkins.&lt;/p&gt;&lt;p&gt;As I blogged before, Maven integration is probably one of the most important features of any CI server (at least for me). I guess Sonatype is doing better with Maven integration &amp;ndash; it's "The Maven Company", right? &amp;ndash; and they are working with Oracle on Hudson. At least, they are putting huge efforts into rock-solid integration. However, after having seen a Sonatype Webinar about their plans with Hudson, I'm not that convinced any more. Current features looked a bit awkward and also does the &lt;a href="http://www.sonatype.com/people/2011/02/guicing-up-hudson-making-life-easier-for-developers-with-jsr-330/"&gt;GWT based UI&lt;/a&gt; they are using. So, from my point of view, this point is not yet decided.&lt;/p&gt;&lt;p&gt;Counting it all together, there are some really good reasons to move from Hudson to Jenkins, so we did.&lt;/p&gt;&lt;h4&gt;How to upgrade&lt;/h4&gt;&lt;p&gt;Now... how do you actually migrate from Hudson to Jenkins? Well, it couldn't be easier. There is a Wiki page about &lt;a href="http://wiki.jenkins-ci.org/display/JENKINS/Upgrading+from+Hudson+to+Jenkins"&gt;Upgrading from Hudson to Jenkins&lt;/a&gt;. To make it short, the involved steps are:&lt;/p&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Backup your current installation &amp;ndash; just for the good feeling.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Change Update Site: In your Hudson, go to &lt;span style="font-style:italic;"&gt;Manage Hudson&lt;/span&gt; &amp;gt; &lt;span style="font-style:italic;"&gt;Plugin Management&lt;/span&gt; &amp;gt; &lt;span style="font-style:italic;"&gt;Advanced&lt;/span&gt; &amp;gt; &lt;span style="font-style:italic;"&gt;Update Site&lt;/span&gt; and enter "http://updates.jenkins-ci.org/update-center.json" as URL for Jenkins update site.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Choose to upgrade automatically on &lt;span style="font-style:italic;"&gt;Manage Hudson&lt;/span&gt; page, just as you did so many times to update Hudson. This will download the new JAR.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Restart Hudson, eh, Jenkins.... and there it is!&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;That's it. Took less than 5 min! Hudson indeed is a drop-in replacement, so you usually do not have to change anything (environment variables, system properties, start scripts, job configuration etc).&lt;/p&gt;&lt;p&gt;Well, there is only one thing: the name of the WAR file is still hudson.war! Is Oracle aware of this? ;-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-2413917405220025184?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/2413917405220025184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2011/03/way-from-hudson-to-jenkins.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2413917405220025184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2413917405220025184'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2011/03/way-from-hudson-to-jenkins.html' title='The Way From Hudson To Jenkins'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-5248046048068498564</id><published>2011-02-27T21:37:00.008+01:00</published><updated>2011-02-27T23:12:13.750+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>The Butler Dispute</title><content type='html'>&lt;p&gt;I thought it would be time to resurrect my blog, after not having posted for a couple of months. That was mainly because I have been really busy with some interesting stuff I should post about in the future, like Xtext upgrade...&lt;/p&gt;&lt;h4&gt;Oracle vs. the Community&lt;/h4&gt;&lt;p&gt;But today, I just bumped the ongoing dispute between Hudson and Jenkins guys. We are using Hudson since around 2008, coming from Cruise Control. We really liked the web interface, being able to setup everything by just using your browser. Of course, the features also have been impressive since then. Setting up a build farm is just fun with Hudson.&lt;/p&gt;&lt;p&gt;You probably know that there has been a fork of Hudson which is named Jenkins (others say Hudson has been renamed to Jenkins and then forked into Hudson). This all started with the Hudson team being unhappy with the infrastructure provided by java.net (which is driven by Oracle since Sun acquisition), due to its poor reliability. The community talked about moving parts of the project to other servers, and first candiate was issue tracking. Suddenly, the project is locked due to the migration of java.net projects to new Kenai infrastructure, which was announced by Oracle but somehow missed by the project owners. Frustrated by the migration, the community decides to move code to GitHub and mailing list to Google Groups. See &lt;a href="http://jenkins-ci.org/content/whos-driving-thing"&gt;"Who's driving this thing?"&lt;/a&gt; for the facts.&lt;/p&gt;&lt;p&gt;This is the point where Oracle steps in, claiming to have a trademark on the name. If the project decides to move, it must be using another name: "Because it is open source, we can't stop anybody from forking it. We do however own the trademark to the name so you cannot use the name outside of the core community. We acquired that as part of Sun." (BTW, that &lt;a href="http://www.theserverside.com/discussions/thread.tss?thread_id=61437"&gt;might not be true&lt;/a&gt; after all). Later he stated that "the final decision of what to do w.r.t. infrastructure belongs to Oracle". &lt;/p&gt;&lt;p&gt;Guess what: this really concerned the community. There have been some &lt;a href="http://jenkins-ci.org/content/hudsons-future"&gt;talks&lt;/a&gt; between key community members and Oracle representives, in an attempt to agree on a "proposal for a stable structure and arrangement" which later would be proposed to the community. But, with no success. That finally led to the &lt;a href="http://kohsuke.org/2011/01/11/bye-bye-hudson-hello-jenkins/"&gt;decision&lt;/a&gt; of the community to move to GitHub and at the same time rename the project to another butler's name: "Jenkins".&lt;/p&gt;&lt;p&gt;Of course, &lt;a href="http://hudson-ci.org/docs/process_summary.html"&gt;Oracle's view&lt;/a&gt; on the subject is a bit different...&lt;/p&gt;&lt;h4&gt;Welcome Jenkins!&lt;/h4&gt;&lt;p&gt;Well, so now you have the choice: use &lt;a href="http://hudson-ci.org/"&gt;Hudson&lt;/a&gt;, or use &lt;a href="http://jenkins-ci.org/"&gt;Jenkins&lt;/a&gt;. You know, competition is usually a good thing, so let the race begin. The majority of the community seems to have made the switch to Jenkins (given the blogs and mailing list traffic). This is because Oracle's behavior is not quite understood and does not cast a positive light on their comprehension of Oracle's role in the Hudson community.&lt;/p&gt;&lt;p&gt;However, Oracle is putting enormous resources (people and hardware) into the Hudson project. And what's even more important, Sonatype is helping to drive Hudson to the next level. Sonatype? Right, that's the company behind Maven and all the great Maven tools like Nexus and m2eclipse.&lt;/p&gt;&lt;h4&gt;Maven Support &amp;ndash; the Killer Feature?&lt;/h4&gt;&lt;p&gt;One of the most important features (for me, but also for possibly the majority of other users) is Maven 3 support. Sure, Hudson/Jenkins already support Maven 3 since version 1.392 (end of 2010, see &lt;a href="http://jenkins-ci.org/changelog"&gt;changelog&lt;/a&gt;). But hey, Sonatype entered the scene, and they will surely do better.&lt;/p&gt;&lt;p&gt;Sonatype, too, have put some full-time engineers into the Hudson project, making sure that "Hudson users can look forward to a long, bright future". See &lt;a href="http://www.sonatype.com/people/2011/02/our-focus-on-advancing-hudson-and-making-great-software/"&gt;this&lt;/a&gt; or &lt;a href="http://www.sonatype.com/people/2011/02/hudsons-bright-future/"&gt;this&lt;/a&gt; post. Sonatype in the end of the day wants to earn money with Hudson (and Maven), so I expect to see outstanding features related to Maven 3 support, Eclipse integration and workflow extensions for Hudson. See &lt;a href="http://www.sonatype.com/people/2009/02/sonatypes-hudson-plans-for-maven-integration/"&gt;here&lt;/a&gt; for some of their ideas.&lt;/p&gt;&lt;p&gt;Well, this really makes a thrilling game. I honestly appreciate what Kohsuke Kawaguchi and others have built up with Hudson from the ground up, and would like to see them win on the "evil company that pushed them out of the project". And by the way, Sonatype seems to be in good companion when talking about being evil &amp;ndash; they &lt;a href="http://www.jroller.com/eu/entry/committer_is_removed"&gt;removed the oldest commiter of m2eclipse&lt;/a&gt; from the project a year ago.&lt;/p&gt;&lt;p&gt;So, is this again the good vs. evil story? I don't know. In the end, both projects will have their users. And they will learn and benefit from each other. So let's wait and see.... Time will tell. It's going to be an interesting year, though!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-5248046048068498564?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/5248046048068498564/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2011/02/butler-dispute.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/5248046048068498564'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/5248046048068498564'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2011/02/butler-dispute.html' title='The Butler Dispute'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-3581710384810822069</id><published>2010-10-15T12:15:00.005+02:00</published><updated>2010-10-15T13:15:19.988+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven 3 and Plugin Mysteries</title><content type='html'>&lt;p&gt;You probably know that &lt;a href="http://www.sonatype.com/people/2010/10/maven-3-0-has-landed/"&gt;Maven 3 has landed&lt;/a&gt;. Before testing it with our projects, I was curious about the plugins that are defined in the Maven master POM's &lt;em&gt;pluginManagement&lt;/em&gt; section and hence are locked-down with respect to their version. Since all projects inherit from this master POM, they will use the respective version of the plugins if not explicitely overwritten anywhere in the project's POM hierarchy.&lt;/p&gt;&lt;p&gt;Maven 3 is a &lt;a href="https://cwiki.apache.org/MAVEN/maven-3x-compatibility-notes.html#Maven3.xCompatibilityNotes-AutomaticPluginVersionResolution"&gt;bit more strict&lt;/a&gt; concerning automatic version resolution of invoked plugins. Other than Maven 2, it will always use the latest release (i.e. non-SNAPSHOT) version of a plugin if there was no explicit version specified in the POM or on the command line. Moreover, it will issue a warning when missing plugin versions are detected "to encourage the addition of plugin versions to the POM or one of its parent POMs". This is to increase reproducability of builds.&lt;/p&gt;&lt;p&gt;Thus, in Maven 3 the desired build stability is ensured by urging the POM author to give explicit plugin versions, and doesn't any more rely on a full list of plugins (with versions) defined in the master POM. That's why I expected to find a small or even empty &lt;em&gt;pluginManagement&lt;/em&gt; section. Well, let's see.&lt;/p&gt;&lt;p&gt;To find out what's in the &lt;em&gt;pluginManagement&lt;/em&gt; of master POM, you just have to create a &lt;a href="http://maven.apache.org/guides/introduction/introduction-to-the-pom.html#Minimal_POM"&gt;minimal POM&lt;/a&gt; and show the &lt;a href="http://maven.apache.org/plugins/maven-help-plugin/effective-pom-mojo.html"&gt;effective POM&lt;/a&gt; (that results from the application of interpolation and inheritance, including master POM and active profiles) by calling &lt;code&gt;help:effective-pom&lt;/code&gt; for this simple project.&lt;/p&gt;&lt;p&gt;So, what do we get? The following list shows the plugin versions that are defined in the Maven 2.2.1 master POM, the Maven 3 master POM, as well as the most recent version of those plugins.&lt;/p&gt;&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/_ey2D_DPIY5E/TLgyBS2y7AI/AAAAAAAAADI/F4QSKGtyErU/s1600/MavenPlugins.gif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 320px;" src="http://2.bp.blogspot.com/_ey2D_DPIY5E/TLgyBS2y7AI/AAAAAAAAADI/F4QSKGtyErU/s400/MavenPlugins.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5528223540420209666" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Well, we can see some interesting details here:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The number of plugins defined in the master POMs &lt;em&gt;pluginManagement&lt;/em&gt; section is drastically less for Maven 3 than for Maven 2.2.1 &amp;ndash; that's what we expected. However, there are still a few.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Which pluings are listed and which are not? It seems like the plugins for the most basic lifecycle phases (like &lt;em&gt;clean&lt;/em&gt;, &lt;em&gt;install&lt;/em&gt;, &lt;em&gt;deploy&lt;/em&gt;) are predefined, but others are not (like &lt;em&gt;compile&lt;/em&gt; or &lt;em&gt;jar&lt;/em&gt;). Is there any policy?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;What is really odd: for some of the plugins that are predefined, there is a newer version available than is listed in the Maven 3 master POM (colored red). Why could that be? I have not checked, but Maven 3 is out for a few days now, so I suspect for most of those plugins the new version has been available before. Is that intentionally? Are the new versions not considered "good" or "stable" by the Maven guys? Or did they just forgot to upgrade? Or did not found it important in any kind?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Another thing I can't explain: when you look on the Maven 3 Project &lt;a href="http://maven.apache.org/ref/3.0/plugin-management.html"&gt;Plugin Management site&lt;/a&gt;, there are listed a lot more plugins, and some are even of other version than what we got by showing the effective POM for a minimal project POM. How could this be? I have no clue...&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In a &lt;a href="http://javamoods.blogspot.com/2009/12/maven-plugins-upgrade-with-care.html"&gt;previous post&lt;/a&gt;, I have listed the plugins predefined by Maven 3.0-alpha5. Interestingly, there have been a lot more of them (like for Maven 2.2.1), but the "stale version" question was the same...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-3581710384810822069?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/3581710384810822069/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/10/maven-3-and-plugin-mysteries.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/3581710384810822069'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/3581710384810822069'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/10/maven-3-and-plugin-mysteries.html' title='Maven 3 and Plugin Mysteries'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_ey2D_DPIY5E/TLgyBS2y7AI/AAAAAAAAADI/F4QSKGtyErU/s72-c/MavenPlugins.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-1492934040585064293</id><published>2010-10-13T17:46:00.005+02:00</published><updated>2010-10-13T18:37:45.382+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='BestPractices'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>World of Versioning</title><content type='html'>&lt;p&gt;Today, we had a discussion on how to name a hotfix release of our framework product, built with Maven (you knew I'm a fan of Maven, didn't you?). It's a very basic question, but still an interesting one and it opens a whole universe of ideas, opinions and rules...&lt;/p&gt;&lt;p&gt;The previous versions of our product had been named like this:&lt;/p&gt;&lt;blockquote&gt;1.3.0. 1.3.1 ... 1.4.0, 1.4.1, ... 1.5.0, 1.5.1, 1.5.2, ... 1.5.6&lt;/blockquote&gt;&lt;p&gt;They all are based on a release plan and contain bugfixes as well as improvements and new features. For each of those versions, we have written release notes and built a site.&lt;/p&gt;&lt;p&gt;Now, what do we do when there is the need to release a bugfix version of a regular release we built a few days ago? There are some options:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;1.5.7 &amp;ndash; i.e. increment last number; however, this doesn't seem to fit well because the bugfix release is of another character than standard releases&lt;/li&gt;&lt;li&gt;1.5.6.1  &amp;ndash; i.e. add an additional numerical identifier&lt;/li&gt;&lt;li&gt;1.5.6.a  &amp;ndash; i.e. add another non-numerical identifier&lt;/li&gt;&lt;li&gt;1.5.6-patch1  &amp;ndash; i.e. add another qualifier describing it's actually a patch release&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;When searching the Net for version number rules in the Maven world, you'll stumble upon the &lt;a href="http://maven.apache.org/ref/current/maven-artifact/xref/org/apache/maven/artifact/versioning/DefaultArtifactVersion.html"&gt;DefaultArtifactVersion&lt;/a&gt; class in the core of Maven which expects that version numbers will follow a specific format:&lt;/p&gt;&lt;blockquote&gt;&amp;lt;MajorVersion [&amp;gt; . &amp;lt;MinorVersion [&amp;gt; . &amp;lt;IncrementalVersion ] ] [&amp;gt; - &amp;lt;BuildNumber | Qualifier ]&amp;gt;&lt;/blockquote&gt;&lt;p&gt;Where &lt;em&gt;MajorVersion&lt;/em&gt;, &lt;em&gt;MinorVersion&lt;/em&gt;, &lt;em&gt;IncrementalVersion&lt;/em&gt; and &lt;em&gt;BuildNumber&lt;/em&gt; are all numeric and &lt;em&gt;Qualifier&lt;/em&gt; is a string. If your version number does not match this format, then the entire version number is treated as being the Qualifier (see &lt;a href="http://mojo.codehaus.org/versions-maven-plugin/version-rules.html"&gt;Versions Maven Plugin&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;This means, options 1 and 4 of above would be a viable alternative in the Maven world. However, note that there is some &lt;a href="http://docs.codehaus.org/display/MAVEN/Versioning"&gt;discussion&lt;/a&gt; about this Maven schema. It suffers from inconsistent/unintuitive parsing, lexically sorting of qualifiers and some other flaws. This would yield to unexpected comparison results especially when using Maven SNAPSHOT versions. The Proposal given on that page seems to be integrated with Maven 3.&lt;/p&gt;&lt;p&gt;Actually, we wouldn't have this discussion if the third level would not be named &lt;em&gt;Incremental version&lt;/em&gt; in Maven world, but rather &lt;em&gt;bugfix version&lt;/em&gt; or &lt;em&gt;patch version&lt;/em&gt;. There is a &lt;a href="http://semver.org/"&gt;Semantic Versioning Specification (SemVer)&lt;/a&gt; that recommends this version schema:&lt;/p&gt;&lt;blockquote&gt;A normal version number MUST take the form X.Y.Z where X, Y, and Z are integers. X is the major version, Y is the minor version, and Z is the patch version. Each element MUST increase numerically. For instance: 1.9.0 &lt; 1.10.0 &lt; 1.11.0.&lt;/blockquote&gt;&lt;p&gt;There are some rules describing when to increase which part. The main idea is to use the first numerical (major version) to indicate backwards incompatible changes to the public API, and in contrast the last numerical (patch version) suggests that only backwards compatible bug fixes have been introduced.&lt;/p&gt;&lt;p&gt;This SemVer schema is fully compatible with Maven (regardless of SNAPSHOT versions). If we had used this, we would probably have ended up in a "higher" version number like 5.4.0, but now the upcoming patch would have the version number 5.4.1 without any consideration.&lt;/p&gt;&lt;p&gt;By the way, a lot of public recommendations for software versioning follow this &lt;em&gt;&amp;lt;major&amp;gt;.&amp;lt;minor&amp;gt;.&amp;lt;patch&amp;gt;&lt;/em&gt; schema. See this &lt;a href="http://stackoverflow.com/questions/2048437/what-version-numbering-scheme-to-use"&gt;question&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Software_versioning"&gt;Wikipedia&lt;/a&gt; for more information on Software Versioning.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So. What do we do now? We'll release a version &lt;em&gt;1.5.6-patch1&lt;/em&gt; for the patch, but think about changing our versioning according to SemVer, i.e. to upgrade the major number when introducing incompatible changes, and the minor number in most other cases.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-1492934040585064293?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/1492934040585064293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/10/world-of-versioning.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1492934040585064293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1492934040585064293'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/10/world-of-versioning.html' title='World of Versioning'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-1793009584906251790</id><published>2010-09-27T13:47:00.009+02:00</published><updated>2010-09-27T15:59:19.599+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Checkstyle'/><title type='text'>Fix Foreign Code</title><content type='html'>&lt;p&gt;Well, finally, I'm back! I have been busy working on-site for a customer of my company, helping to fix their project and increase quality to successfully conduct the rollout. Additionally, I spent my evenings working as a release manager and keeper of the Maven based infrastructure for several projects developed in-house. So this was more than a fulltime job and unfortunately no time was left to read or write blog posts :-(&lt;/p&gt;&lt;p&gt;However, that project assignment is nearly over now and I intend to write more regularly now about my findings, trials and tribulations.&lt;/p&gt;&lt;h4&gt;Foreign Code Dilemma&lt;/h4&gt;&lt;p&gt;My main task when working for our customer was to fix bugs and improve quality of their application, which was nearly completely implemented with respect to use cases and business requirements. This is a situation that might be known to most developers: you are thrown into a project you don't know much of, lots of source code is already implemented, quality is, well, varying, and some important milestone or release date is right ahead. This is what I call the &lt;span style="font-style:italic;"&gt;Foreign Code Dilemma&lt;/span&gt;. &lt;/p&gt;&lt;p&gt;What do you do to quickly get up to speed and rescue the project? Well, there are some things that I find quite useful in situations like this. In no particular order...&lt;/p&gt;&lt;h4&gt;Introduce Continuous Integration&lt;/h4&gt;&lt;p&gt;It should be common sense these days that Continuous Integration (CI) is able to improve software quality and reduce integration issues as well as overall risks. CI is a software development practice where changes are integrated frequently &amp;ndash; usually at least daily &amp;ndash; and the result is verified by an automated build and test to detect issues as quickly as possible. The distinguished article about &lt;a href="http://martinfowler.com/articles/continuousIntegration.html"&gt;Continuous Integration&lt;/a&gt; by Martin Fowler is a must-read.&lt;/p&gt;&lt;p&gt;Fortunately, the customer's project already provided automated Ant build scripts to checkout, build and test the software. Moreover, they were running on a Cruise Control server each night, so we were quite close.&lt;/p&gt;&lt;p&gt;The first thing I did was to move to &lt;a href="http://hudson-ci.org/"&gt;Hudson&lt;/a&gt;, the best integration server available today (if you'd ask me). The transition was quite smooth and done within a few hours, including setting up a brand new build server. If you're still using Cruise Control, you really should consider to move over to Hudson... I think I should post about the cool distribution feature of Hudson soon.&lt;/p&gt;&lt;p&gt;One issue with the project was the build time: a full build takes 3-4 hours, mainly due to long-running unit and selenium test cases. Of course, this inhibits doing real CI. All we could do for now was to split up the build into the four main tasks, creating a Hudson job for each of them: (1) checkout &amp; compile &amp; package, (2) static code checks, (3) unit tests, (4) selenium tests. Since (1) and (2) are running rather quick (about 10 min) those jobs qualify for CI builds. This is not perfect but still better than doing no CI at all.&lt;/p&gt;&lt;h4&gt;Introduce Test Cases&lt;/h4&gt;&lt;p&gt;Test cases are an essential part of a software development project these days, and I always consider a tasks not being finished unless there are test cases ensuring that the functionality is implemented correctly. I'm sure you agree ;-)&lt;/p&gt;&lt;p&gt;The project I was working on had lots of JUnit test cases, as well as hundreds of Selenium tests checking the web application in the browser. That's not bad, really. Nevertheless, there were two issues:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The number of test cases does not tell anything about the test coverage. For example, the Selenium tests all did test a "happy day" scenario, moving through the wizard pages of the web application straight from the first to the end. But does it still work, for instance, if you step to the forth page, choose some options on that page, step back two pages, change an option, and go to the forth page again? Nobody tested.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Selenium web tests are slow, which is no surprise taken the fact that the tests are running in a browser and need to connect to the deployed web application. In my project, the full test suite took more than 3 hours to run... What's even worse is that some of the JUnit tests have not been designed as unit tests, i.e. they required a full service stack to run successfully, as such being more an integration than a unit test. As a consequence, those tests require to startup all services which takes a lot of time.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Thus, the task for this project actually was not to introduce, but to improve unit tests: increase code coverage and separate unit from integration tests. This way, unit tests can be run within CI builds, providing a quick result for the quality of committed code.&lt;/p&gt;&lt;h4&gt;Introduce Code Metrics&lt;/h4&gt;&lt;p&gt;When more than a few people are working on a project, establishing a coding standard is usually a rewarding idea. It helps you to be comfortable with the sources of anybody else from your team, and when doing code comparison you don't see differences all the time that are just caused by reformatting, hiding the significant changes.&lt;/p&gt;&lt;p&gt;If you have defined such coding standards, you need to check them. &lt;a href="http://checkstyle.sourceforge.net/"&gt;Checkstyle&lt;/a&gt; is the tool of choice. Here is what you should do:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Define a Checkstyle configuration to be used for your project. Discuss the rules with developers and stakeholders.&lt;/li&gt;&lt;li&gt;Run Checkstyle with your CI and/or nightly builds to create a report, including a list of violations for defined rules.&lt;/li&gt;&lt;li&gt;Establish Checkstyle within your IDE of choice to provide immediate feedback to the developers &lt;span style="font-style:italic;"&gt;before&lt;/span&gt; they commit.&lt;/li&gt;&lt;li&gt;Define which exceptions to the rule are acceptable (should not be more than a dozen or so) and suppress them permanently, using Checkstyle suppression filters.&lt;/li&gt;&lt;li&gt;Get rid of all remaining violations, which might take a few days of effort. Still, this investment will pay off.&lt;/li&gt;&lt;li&gt;Once the number of Checkstyle violations is "small" (meaning less than 10, ideally zero), make sure it remains small.&lt;/li&gt;&lt;li&gt;Establish a team culture where committing code with Checkstyle violations is anything else but cool.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That works quite well in my experience. For the mentioned project, we already had common Eclipse formatting settings, but Checkstyle helped to further improve the code and people adopted it right from the start.&lt;/p&gt;&lt;h4&gt;The Debugger is Your Best Friend&lt;/h4&gt;&lt;p&gt;When you have to fix bugs in code you have never seen before, use the debugger as much as possible. To find the hot spot, you usually don't have to read or understand the whole class or even hierarchies of classes. Thus, it'll save you a lot of time when you don't start with code reviews but use the debugger to find the piece of code to blame.&lt;/p&gt;&lt;p&gt;BTW, the same applies to the look and feel of web applications. Instead of consulting lots of layout code and stylesheets, use browser tools like &lt;a href="http://getfirebug.com/"&gt;Firebug&lt;/a&gt; to debug pages, styles and JavaScript code (including Ajax requests) right in the displayed page.&lt;/p&gt;&lt;p&gt;Of course, this approach is not appropriate when fixing larger design issues...&lt;/p&gt;&lt;h4&gt;Don't Be Shy!&lt;/h4&gt;&lt;p&gt;When using this toolset, you shouldn't be shy. If you think some code needs refactoring, do so &amp;ndash; maybe not a week before going live, but you get the point. The CI build should give you immediate feedback if the change could be integrated, and the tests will tell you if everything still works. Take your chance to improve the code. If your change anyhow is causing an issue, fix it, add another test and don't be discouraged!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-1793009584906251790?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/1793009584906251790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/09/fix-foreign-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1793009584906251790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1793009584906251790'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/09/fix-foreign-code.html' title='Fix Foreign Code'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-9106751119801352716</id><published>2010-04-19T15:37:00.003+02:00</published><updated>2010-04-19T16:39:27.818+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>HDD / SSD Battle</title><content type='html'>&lt;h4&gt;The Problem&lt;/h4&gt;&lt;p&gt;You know, the laptop I'm using for my daily work job is not the fastest one. In contrast, it's more than 5 years old and pretty slow. Yeah I know, hardware can never be fast enought, but it's really slow considering the things I have to work on.&lt;/p&gt;&lt;p&gt;For instance, we are using &lt;a href="http://www.eclipse.org/modeling/tmf/"&gt;xtext&lt;/a&gt; modeling and hence usually have a couple of Eclipse instances running at the same time (outer &amp; inner workbench), additionally to using &lt;a href="http://m2eclipse.sonatype.org/"&gt;m2eclipse&lt;/a&gt; to build the projects with Maven in Eclipse. Moreover, we have some quite big workspaces with tens of thousands of class files.&lt;/p&gt;&lt;p&gt;All of this is probably not unusual, but unfortunately too much for my poor old laptop. It takes minutes to start or end Eclipse, not to mention the times required for cleaning all projects. However, my company currently does not really like the idea to buy new laptops so we have to find ways to speed things up without spending too much money. I have blogged before about some ways to &lt;a href="http://javamoods.blogspot.com/2009/10/speeding-up-your-system.html"&gt;speeding up your system&lt;/a&gt;.&lt;/p&gt;&lt;h4&gt;The Solution?&lt;/h4&gt;&lt;p&gt;It's pretty clear that the bottleneck is the hard drive currently. We have proven this by some inspection tools, the drive is working hard all the time when executing some build, for instance. Now we managed to get a &lt;a href="http://en.wikipedia.org/wiki/Solid-state_drive"&gt;solid state drive&lt;/a&gt; (SSD) to test the performance improvements it would offer. Well, fasten your seatbelt...&lt;/p&gt;&lt;p&gt;We have measured some typical tasks with real data and projects on a developer's laptop &amp;ndash; first with the built-in hard disk, then after installing the SSD and copying the harddrive content over. Note that we have tried to make a fair comparison, keeping the setup indentical in both scenarios. These are the results.&lt;/p&gt;&lt;h4&gt;The Battle&lt;/h4&gt;&lt;p&gt;Working With Eclipse:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Start Eclipse 3.5.1 with an empty workspace until Welcome screen is displayed: 52 s &amp;rarr; 12 s (factor 4.3)&lt;/li&gt;&lt;li&gt;Start Eclipse with a medium-size workspace: 125 s &amp;rarr; 30 s (factor 4.2)&lt;/li&gt;&lt;li&gt;Clean all projects in that workspace: 445 s &amp;rarr; 115 s (factor 3.9) &lt;/li&gt;&lt;li&gt;Exit Eclipse and wait until workspace is saved: 28 s &amp;rarr; 7 s (factor 4.0)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Working With Maven:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Maven "clean install" in mdium-size project: 668 s &amp;rarr; 336 s (factor 2.0)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Booting Windows:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Turn on computer and wait for login screen: 62 s &amp;rarr; 33 s (factor 1.9)&lt;/li&gt;&lt;li&gt;After login, until Windows is ready (autostart applications are loaded): 135 s &amp;rarr; 44 s (factor 3.1)&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;The Bottom Line&lt;/h4&gt;&lt;p&gt;As you can see, the SSD is speeding up boot time by factor 2-3, which already is impressive. Maven build usually gets executed 2 times faster. Eclipse speed-up is even more, namely around factor 4. That's pretty cool! You really feel the performance difference!&lt;/p&gt;&lt;p&gt;Additionally, after some more weeks of testing, what we like most is that the whole system feels much more reactive; that is, when executing some big job like rebuild a huge workspace, you can switch context and nicely work in another instance of Eclipse, for instance &amp;ndash; a single tasks is not blocking the whole system any more.&lt;/p&gt;&lt;p&gt;All in all, that's an incredible speed-up considering the prices of SSD! Now, go and tell your boss ;-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-9106751119801352716?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/9106751119801352716/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/04/hdd-ssd-battle.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/9106751119801352716'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/9106751119801352716'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/04/hdd-ssd-battle.html' title='HDD / SSD Battle'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-3193521161456889378</id><published>2010-03-26T16:20:00.004+01:00</published><updated>2010-03-26T17:19:42.773+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Having Fun with Encoding!</title><content type='html'>&lt;h4&gt;Compiler Plugin&lt;/h4&gt;&lt;p&gt;Recently, I edited our main company root POM to upgrade some plugins to new versions. Of course, we are following best practice to &lt;a href="http://www.sonatype.com/people/2008/05/optimal-maven-plugin-configuration/"&gt;lock down the plugin version&lt;/a&gt;, so when a new version is available we only need to adjust the parent POM. Nearly all version updates were on the last build number digit, which is the &lt;em&gt;z&lt;/em&gt; in &lt;em&gt;x.y.z&lt;/em&gt; version string &amp;ndash; so I didn't expect much difficulties.&lt;/p&gt;&lt;p&gt;However, for the &lt;a href="http://maven.apache.org/plugins/maven-compiler-plugin/"&gt;compiler plugin&lt;/a&gt;, it was a jump from version 2.0.2 to 2.1, and indeed it turned out that some of the test cases failed compiling with strange encoding issues when using the new compiler plugin version.&lt;/p&gt;&lt;h4&gt;Specify Encoding&lt;/h4&gt;&lt;p&gt;We are following the suggestion to specify a &lt;a href="http://docs.codehaus.org/display/MAVENUSER/POM+Element+for+Source+File+Encoding"&gt;POM property for source file encoding&lt;/a&gt;, for not being forced to configure encoding for all relevant plugins individually. Moreover, we were exactly using what's shown in the example:&lt;pre class="brush:xml"&gt;&amp;lt;project&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;  &amp;lt;properties&amp;gt;&lt;br /&gt;    &amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;  &amp;lt;/properties&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;&amp;lt;/project&amp;gt;&lt;/pre&gt;That is, we assumed our source files were &lt;a href="http://en.wikipedia.org/wiki/UTF-8"&gt;UTF-8&lt;/a&gt; encoded, which is the most widely used encoding for unicode characters. But, for some of the projects, that's actually not the case since we are using Eclipse with the default setting for text file encoding which is &lt;a href="http://en.wikipedia.org/wiki/Windows-1252"&gt;Cp1252&lt;/a&gt; (Western European) on our german Windows.&lt;/p&gt;&lt;p&gt;Why didn't we ever notice that? Well, it happens that both the UTF-8 as well as Cp1252 encodings are backwards compatible with ASCII. We are coding most of the stuff in english (concerning package, class, method, attribute and parameter names, and even Javadoc comments), so the resulting byte stream will never be different for both encodings. However, some of the files used german umlauts in line comments which are exactly the files that can't be compiled any more with new compiler plugin version.&lt;/p&gt;&lt;p&gt;When looking at the debug output of compiler plugin 2.0.2 mojo configuration, you can see that the encoding is not explicitely set, probably meaning that the platform default encoding is used (which is again Cp1252 on all build machines):&lt;/p&gt;&lt;pre class="brush:xml"&gt;[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-compiler-plugin:2.0.2:compile' --&gt;&lt;br /&gt;[DEBUG]   (f) basedir = ...&lt;br /&gt;[DEBUG]   (f) buildDirectory = ...&lt;br /&gt;[DEBUG]   (f) classpathElements = [...]&lt;br /&gt;[DEBUG]   (f) compileSourceRoots = [...]&lt;br /&gt;[DEBUG]   (f) compilerId = javac&lt;br /&gt;[DEBUG]   (f) debug = true&lt;br /&gt;[DEBUG]   (f) failOnError = true&lt;br /&gt;[DEBUG]   (f) fork = false&lt;br /&gt;[DEBUG]   (f) optimize = true&lt;br /&gt;[DEBUG]   (f) outputDirectory = ...&lt;br /&gt;[DEBUG]   (f) outputFileName = xxx-0.2.0-SNAPSHOT&lt;br /&gt;[DEBUG]   (f) projectArtifact = xxx:jar:0.2.0-SNAPSHOT&lt;br /&gt;[DEBUG]   (f) showDeprecation = false&lt;br /&gt;[DEBUG]   (f) showWarnings = false&lt;br /&gt;[DEBUG]   (f) source = 1.6&lt;br /&gt;[DEBUG]   (f) staleMillis = 0&lt;br /&gt;[DEBUG]   (f) target = 1.6&lt;br /&gt;[DEBUG]   (f) verbose = false&lt;br /&gt;[DEBUG] -- end configuration --&lt;/pre&gt;&lt;p&gt;The new version 2.1 of compiler plugin is now considering what has been configured in &lt;code&gt;project.build.sourceEncoding&lt;/code&gt; property, and hence tries to compile the Cp1252 coded source file with UTF-8 encoding which doesn't work when umlauts are used.&lt;/p&gt;&lt;h4&gt;Specify Correct Encoding&lt;/h4&gt;&lt;p&gt;Of course, the solution is to specify the correct encoding in &lt;code&gt;project.build.sourceEncoding&lt;/code&gt; property, matching the encoding that is used in the development environment when writing the source files.&lt;/p&gt;&lt;p&gt;Oh, yes, Cp1252 is quite similar to ISO 8859-1 encoding (only some special characters on positions 0x80–0x9F are different which we don't use), so in fact we are using ISO 8859-1 now to allow builds on non-Windows platforms as well.&lt;/p&gt;&lt;p&gt;Certainly, it would be nice if the plugins had a history on their site where you can find this type of changes for new versions, without having to search in the Jira...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-3193521161456889378?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/3193521161456889378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/03/having-fun-with-encoding.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/3193521161456889378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/3193521161456889378'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/03/having-fun-with-encoding.html' title='Having Fun with Encoding!'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-2178835090822368252</id><published>2010-02-26T15:30:00.003+01:00</published><updated>2010-02-26T16:52:46.283+01:00</updated><title type='text'>Eclipse: Update Manager Needs Update!</title><content type='html'>&lt;p&gt;Eclipse Update Manager is really a special piece of software... I have &lt;a href="http://javamoods.blogspot.com/2009/05/eclipse-update-manager-fools-me.html"&gt;blogged before&lt;/a&gt; about my battle, and here is another one.&lt;/p&gt;&lt;p&gt;We have a simple Eclipse plugin (created by xtext to provide an editor for our DSL, but actually this doesn't matter). I have a particular version (let's say 1.0.0) of that installed in my Eclipse 3.5.1. Now I want to upgrade to 1.1.0, but unfortunately the feature id has changed, so I need to uninstall my 1.0.0 version prior to installing the new one.&lt;/p&gt;&lt;p&gt;But... when I try to uninstall this plugin Eclipse tells me that it is "Calculating requirements and dependencies". To do so, Eclipse downloads a lot of stuff, including Eclipse features, mylyn, and much more. Seems to be half the internet which takes while. And then, about 15 min later, Eclipse tells me that it could not find a download site for some weird mozilla plugin.&lt;/p&gt;&lt;p&gt;Hello? What's that? I want to &lt;em&gt;uninstall&lt;/em&gt; a plugin and Eclipse &lt;em&gt;downloads&lt;/em&gt; tons of jars only to tell me that one is missing and it couldn't uninstall? Gosh!&lt;/p&gt;&lt;p&gt;After some googling, I found a trick to force Eclipse to just do what I want:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;In Eclipse &lt;em&gt;Preferences&lt;/em&gt;, on &lt;em&gt;Install/Update &gt; Available Software Sites&lt;/em&gt; page, export all sites to your filesystem.&lt;/li&gt;&lt;li&gt;Then remove all update sites and press OK.&lt;/li&gt;&lt;li&gt;Now uninstall the plugin -- for me, it just worked like a charm.&lt;/li&gt;&lt;li&gt;After restarting Eclipse, open &lt;em&gt;Install/Update &gt; Available Software Sites&lt;/em&gt; again and import the previously exported update sites.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;That's it. Maybe just pulling the network cable would have worked, too... Oh boy.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-2178835090822368252?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/2178835090822368252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/02/eclipse-update-manager-needs-update.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2178835090822368252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2178835090822368252'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/02/eclipse-update-manager-needs-update.html' title='Eclipse: Update Manager Needs Update!'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-728787268480307175</id><published>2010-02-20T13:54:00.003+01:00</published><updated>2010-02-20T15:36:35.070+01:00</updated><title type='text'>Maven vs. Ant: Stop the Battle</title><content type='html'>&lt;h4&gt;Maven? Ant?&lt;/h4&gt;&lt;p&gt;Oh boy, how this bothers me. The endless debate and religious battle about which build tool is the better build tool, no, is the one and only &lt;em&gt;right&lt;/em&gt; build tool...&lt;/p&gt;&lt;p&gt;There are many people out there who love Ant, who defend Ant with their blood and honour. That's fine, but some of them at the same time shoot at Maven. There is so much rant about Maven, so much unfair allegation and just plain wrong claims. &lt;a href="http://kent.spillner.org/blog/work/2009/11/14/java-build-tools.html"&gt;This&lt;/a&gt; is just one example that has been &lt;a href="http://www.wakaleo.com/blog/246-maven-mythbusters-maven-automatically-updates-for-every-build"&gt;discussed&lt;/a&gt; in the community lately.&lt;/p&gt;&lt;p&gt;Don't get me wrong. Maven has its flaws and issues, sure, and you don't have to like it. Use Ant, or &lt;a href="http://www.gradle.org/"&gt;Gradle&lt;/a&gt;, or &lt;a href="http://buildr.apache.org/"&gt;Buildr&lt;/a&gt;, or &lt;a href="http://www.schmant.org/"&gt;Schmant&lt;/a&gt;, or batch files, or anything else if you like that more. But, Maven definitely &lt;em&gt;can&lt;/em&gt; be used to build complex software projects, and lots of people are doing exactly that; and guess what -- some of them even like this tool... So, can everybody just please use what he or she likes the most for building their software, and stop throwing mud at each other? Let's get back to work. Let's put our effort in building good software.&lt;/p&gt;&lt;h4&gt;We've Come a Long Way...&lt;/h4&gt;&lt;p&gt;You may have guessed, I think Maven is the best build tool, at least for the type of projects I am dealing with in my company. We have started using a complex system of mutual calling batch files long time ago, and switched to Ant in 2000. That was a huge step ahead, but still it was a complex system with lots of Ant-Scripts on different levels. So we moved to Maven 1.0.2 in 2004 for another project. That brought nice configuration and reporting features, but still did not feel right, especially for multi-module projects that were not supported in the Maven core at that time. &lt;/p&gt;&lt;p&gt;When Maven 2 came out, we adopted that early and suffered from many teething troubles, but nevertheless we were sure to be on the right track. Today, Maven is a mature, stable, convenient build tool for all our projects, and the first time we are quite happy with how it works and what it provides. Moreover, it sound really great what the brave guys from &lt;a href="http://www.sonatype.com/"&gt;Sonatype&lt;/a&gt; have in their pipeline: &lt;a href="http://www.sonatype.com/people/2009/11/maven-30-alpha-3-released/"&gt;Maven 3&lt;/a&gt;, Tycho, and all those nice tools like Nexus and m2eclipse...&lt;/p&gt;&lt;p&gt;Hence, I am happy and honestly don't really care very much about what the blogosphere is telling about Maven. But the sad thing is, my colleagues (mostly used to Ant build systems) are complaining with the same weird theses about Maven. I'll give you one example.&lt;/p&gt;&lt;h4&gt;The Inhouse Battle&lt;/h4&gt;&lt;p&gt;In my current project, we create EJBs in some JARs and assemble an EAR file for the whole application. Now we have to create another RAR to be put in the EAR, so I setup a new project (following Maven's convention "one project, one artifact") for the RAR. This is what the "Ant guys" didn't like: "Why can't Maven create that RAR within the main project, you know Ant could do that, so maybe we should use Ant here again, why have so many small projects, this is polluting our Eclipse's Project View, so much complexity, Maven sucks, I knew that before, blah blah..."&lt;/p&gt;&lt;p&gt;Well, I tried to explain that Maven of course can be configured to create &lt;a href="http://www.sonatype.com/people/2010/01/how-to-create-two-jars-from-one-project-and-why-you-shouldnt/"&gt;multiple artifacts per project&lt;/a&gt;, but that's not the recommended way because it violates Maven convention. It's all about modularity and standardization. That is how Maven works, and it's great this way. A small project is not much overhead at all, it is going to have a clean and simple POM, and by the way we discovered a dependency cycle in the code that had to be fixed in order to move the RAR code into a separate module.&lt;/p&gt;&lt;p&gt;So, what's wrong with Maven? Is it just that you want to do it your way and not to subordinate the Maven way? A matter of honor and ego? Is that enough to kick out Maven and go back to your Ant and script based build system (which BTW is so complex that only few guys really know how it works)? Come on.&lt;/p&gt;&lt;h4&gt;The Bottom Line&lt;/h4&gt;&lt;p&gt;IMHO, standardization of build systems is one of the main benefits that Maven brought to the world. If you know one Maven project, you can switch to any other project built with Maven and feel comfortable immediately. This increases productivity, both personally and for your company, which is one of the reasons more and more companies switch over &lt;a href="http://www.leshazlewood.com/?p=55"&gt;from Ant to Maven&lt;/a&gt;.&lt;br /&gt;We have clean conventions, a nice project structure, and a highly modular system. And, we have world class reporting with minimal effort.&lt;/p&gt;&lt;p&gt;You see, that's why we are using Maven. If you don't like it, go your own way but let us just do our job.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-728787268480307175?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/728787268480307175/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/02/maven-vs-ant-stop-battle.html#comment-form' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/728787268480307175'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/728787268480307175'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/02/maven-vs-ant-stop-battle.html' title='Maven vs. Ant: Stop the Battle'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-7007454795706722851</id><published>2010-02-08T11:39:00.002+01:00</published><updated>2010-02-08T12:09:55.338+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>@Override Changes in Java 6</title><content type='html'>&lt;p&gt;Today I have ported a Java 6 project back to Java 5. This led to compiler failures in Eclipse, but not in Maven which seemed quite strange at first glance. Interestingly, they are caused by the &lt;code&gt;@Override&lt;/code&gt; annotation.&lt;/p&gt;&lt;p&gt;The &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/"&gt;Java 5 API&lt;/a&gt; for &lt;code&gt;@Override&lt;/code&gt; says:&lt;/p&gt;&lt;p&gt;&lt;dl&gt;&lt;dt&gt;&lt;/dt&gt;&lt;dd&gt;Indicates that a method declaration is intended to override a method declaration in a superclass. If a method is annotated with this annotation type but does not override a superclass method, compilers are required to generate an error message.&lt;/dd&gt;&lt;/dl&gt;&lt;/p&gt;&lt;p&gt;Note that it says "superclass", not "supertype". Hence, it's not allowed to add this annotation to methods that implement methods of an interface. Javac (which is called by Maven) does not report this as an error, but the Eclipse compiler does.&lt;/p&gt;&lt;p&gt;Well, if you take a look at &lt;a href="http://java.sun.com/javase/6/docs/api/index.html"&gt;Java 6&lt;/a&gt;, the API didn't change at all so I was surprised to see a different behavior: the &lt;code&gt;@Override&lt;/code&gt; annotation is allowed for methods implementing interface methods in Javac, too. In the end, I had to remove those annotations to make the code compile with Java 5 in Eclipse.&lt;/p&gt;&lt;p&gt;After some googling, I found out that this has just been forgotten by Sun developers: the compiler's behavior is changed but the documentation does not reflect that (see &lt;a href="http://blogs.sun.com/ahe/entry/override_snafu"&gt;here&lt;/a&gt;). And indeed, when you look at the API of &lt;code&gt;@Override&lt;/code&gt; in upcoming &lt;a href="http://download.java.net/jdk7/docs/api/index.html"&gt;Java 7&lt;/a&gt; it looks like:&lt;/p&gt;&lt;p&gt;&lt;dl&gt;&lt;dt&gt;&lt;/dt&gt;&lt;dd&gt;Indicates that a method declaration is intended to override a method declaration in a supertype. If a method is annotated with this annotation type compilers are required to generate an error message unless at least one of the following conditions hold:&lt;ul&gt;&lt;li&gt;The method does override or implement a method declared in a supertype.&lt;/li&gt;&lt;li&gt;The method has a signature that is override-equivalent to that of any public method declared in Object.&lt;/li&gt;&lt;/ul&gt;&lt;/dd&gt;&lt;/dl&gt;&lt;/p&gt;&lt;p&gt;Here you got it: &lt;code&gt;@Override&lt;/code&gt; may now bee used for interface methods, too.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-7007454795706722851?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/7007454795706722851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/02/override-changes-in-java-6.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7007454795706722851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7007454795706722851'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/02/override-changes-in-java-6.html' title='@Override Changes in Java 6'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-8223904428722384669</id><published>2010-02-02T15:49:00.004+01:00</published><updated>2010-02-02T16:50:50.090+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimization'/><title type='text'>Optimization: Don't do it... The compiler will!</title><content type='html'>&lt;h4&gt;The Two Rules of Program Optimization&lt;/h4&gt;&lt;p&gt;I've seen some bad code lately which was designed in an effort to improve performance. For instance, there was a long method (80 lines) that was not split into several methods for a single reason: to avoid the method call overhead (around 15 nanoseconds!). The result was code that was just hard to read.&lt;/p&gt;&lt;p&gt;This reminded me of the rules of program optimization (coined by Michael A. Jackson, a British computer scientist) we were teached back on university:&lt;br /&gt;&lt;strong&gt;The First Rule of Program Optimization:&lt;/strong&gt; Don't do it.&lt;br /&gt;&lt;strong&gt;The Second Rule of Program Optimization (for experts only!):&lt;/strong&gt; Don't do it yet.&lt;/p&gt;&lt;p&gt;Well, this is true for mainly two reasons:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Optimization can reduce readability and add code that is used only to improve the performance. This may complicate programs or systems, making them harder to maintain and debug.&lt;/li&gt;&lt;li&gt;Doing optimizations most of the time means we think to be smarter than the compiler, which is just plain wrong more often than not.&lt;/li&gt;&lt;/ol&gt;&lt;h4&gt;Cleaner Code&lt;/h4&gt;&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Donald_Knuth"&gt;Donald Knuth&lt;/a&gt; said "Premature optimization is the root of all evil". Whereas "Premature optimization" means that a programmer lets performance considerations drive the design of his code. This can result in a design that is not as clean as it could have been, because the code is complicated by the optimization and the programmer is distracted by optimizing.&lt;/p&gt;&lt;p&gt;Therefore, if performance tests reveal that optimization or performance tuning really have to be done, they usually should be done at the end of the development stage.&lt;/p&gt;&lt;h4&gt;Wrong Intuitions&lt;/h4&gt;&lt;p&gt;This is what Sun Microsystem's Technology Evangelist &lt;a href="http://java.sun.com/developer/technicalArticles/Interviews/goetz_qa.html"&gt;Brian Goetz&lt;/a&gt; thinks: "Most performance problems these days are consequences of architecture, not coding – making too many database calls or serializing everything to XML back and forth a million times. These processes are usually going on outside the code you wrote and look at every day, but they are really the source of performance problems. So if you just go by what you're familiar with, you're on the wrong track. This is a mistake that developers have always been subject to, and the more complex the application, the more it depends on code you didn't write. Hence, the more likely it is that the problem is outside of your code." Right he is!&lt;/p&gt;&lt;h4&gt;Smarter Compiler&lt;/h4&gt;&lt;p&gt;Often, the best way to write fast code in Java applications is to write dumb code – code that is straightforward, clean, and follows the most obvious object-oriented principles in order to get the best compiler optimization. Compilers are big pattern-matching engines, written by humans who have schedules and time budgets, so they focus their efforts on the most common code patterns, in order to get the most leverage. Usually hacked-up, bit-banging code that looks really clever will get poorer results because the compiler can't optimize effectively.&lt;/p&gt;&lt;p&gt;A good example is string concatenation in Java (see &lt;a href="http://java.sun.com/developer/technicalArticles/Interviews/community/kabutz_qa.html"&gt;this conversation&lt;/a&gt; with Java Champion Heinz Kabutz where he gives some measures)...&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Back in the early days, we all used the String addition (+ operator) to concatenate Strings:&lt;br /&gt;&lt;code&gt;return s1 + s2 + s3;&lt;/code&gt;&lt;br /&gt;However, since Strings are immutable, the compiled code will create many temporary String objects, which can strain the garbage collector.&lt;/li&gt;&lt;li&gt;That's why we were told to use StringBuffer instead:&lt;br /&gt;&lt;code&gt;return new StringBuffer().append(s1).append(s2).append(s3).toString();&lt;/code&gt;&lt;br /&gt;That was around 3-5 times faster those days, but the code became less readable. Was it worth it? Is your code doing enough String concatenation to make you really feel a difference after you (for instance) made that execute three times faster?&lt;/li&gt;&lt;li&gt;Is that still the recommended way? A main downside of StringBuffer is its thread safety that is usually not required (since they are not shared between threads), but slows things down. Hence, the StringBuilder class was introduced in Java 5, which is almost the same as StringBuffer, except it's not thread-safe. So, using StringBuilder is expected to be significantly faster, and know what? When Strings are added using the + operator, the compiler in Java 5 and 6 will automatically use StringBuilder:&lt;br /&gt;&lt;code&gt;return s1 + s2 + s3;&lt;/code&gt;&lt;br /&gt;Clean, easy to understand, and quick. Note that this optimization will not occur if StringBuffer is hard-coded!&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;That was just one example.... All in all, it's quite simple: today's Java JIT Compilers are highly optimized and clever in optimizing your code. Trust them. Don't try to be even more clever. You aren't!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-8223904428722384669?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/8223904428722384669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/02/optimization-dont-do-it-compiler-will.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/8223904428722384669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/8223904428722384669'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/02/optimization-dont-do-it-compiler-will.html' title='Optimization: Don&apos;t do it... The compiler will!'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-8116423298985213141</id><published>2010-01-13T10:26:00.004+01:00</published><updated>2010-01-13T11:39:06.180+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Hudson'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Concurrent Builds with Hudson</title><content type='html'>&lt;h4&gt;Multiple Build Executors&lt;/h4&gt;&lt;p&gt;We are using the &lt;a href="http://hudson-ci.org/"&gt;Hudson&lt;/a&gt; Continuous Integration Server for our integration builds and are quite happy with it. It is fast, stable, feature-rich, extensible, well integrated with Maven and has an appealing user interface.&lt;/p&gt;&lt;p&gt;One of the nice features that we are using regularly is the Build Executor setting that allows you to specify the number of simultaneous builds. This is useful to increase throughput of Hudson on multi-core processor systems, where the number of executors should (at least) match the number of available cores.&lt;/p&gt;&lt;p&gt;However, Maven isn't really designed for running multiple instances simultaneously since the local respository isn't multi-process safe. The chance for conflicts seems small (multiple processes must access the same dependency at the same time, at least one of them writing). However, in praxis, we encounter this type of concurrency issue at least once a day now, which is starting to hurt us! The build is failing with a message like this:&lt;/p&gt;&lt;pre class="brush:xml"&gt;[INFO] ------------------------------------------------------------------------&lt;br /&gt;[ERROR] BUILD ERROR&lt;br /&gt;[INFO] ------------------------------------------------------------------------&lt;br /&gt;[INFO] Failed to resolve artifact.&lt;br /&gt;&lt;br /&gt;GET request of: some/group/some-artifact-1.2.3-SNAPSHOT.jar from my-repo failed&lt;br /&gt;  some.group:some-artifact:jar:1.2.3-SNAPSHOT&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;Caused by I/O exception: ...some-artifact-1.2.3-SNAPSHOT.jar.tmp (The requested operation cannot be performed on a file with a user-mapped section open)&lt;/pre&gt;&lt;p&gt;or this:&lt;/p&gt;&lt;pre class="brush:xml"&gt;[INFO] ------------------------------------------------------------------------&lt;br /&gt;[ERROR] BUILD ERROR&lt;br /&gt;[INFO] ------------------------------------------------------------------------&lt;br /&gt;[INFO] Failed to resolve artifact.&lt;br /&gt;&lt;br /&gt;Error copying temporary file to the final destination: Failed to copy full contents from ...some-artifact-1.2.3-SNAPSHOT.jar.tmp to ...\some-artifact-1.2.3-SNAPSHOT.jar&lt;/pre&gt;&lt;p&gt;The reason is, the JAR file is locked by another process that is executing some long-lasting test cases, for instance. At the same time, a second build tries to download a new version of this snapshot into the local repository, which is done with the help of the mentioned &lt;code&gt;.tmp&lt;/code&gt; file.&lt;/p&gt;&lt;h4&gt;Safe Maven Repository&lt;/h4&gt;&lt;p&gt;The only way to avoid this type of issue is to use separate local Maven Repositories for each of the processes. You can tell Maven to use a custom local repository location by specifying the &lt;a href="http://maven.apache.org/ref/2.2.1/maven-settings/settings.html#class_settings"&gt;&lt;em&gt;localRepository&lt;/em&gt; setting&lt;/a&gt; in your &lt;code&gt;settings.xml&lt;/code&gt; file.&lt;/p&gt;&lt;p&gt;In Hudson, this is even more convenient. There is a checkbox &lt;em&gt;Use private Maven repository&lt;/em&gt; in the advanced part of the &lt;em&gt;Build&lt;/em&gt; section of Maven projects. Just click that to setup a private local Maven repo for that project. You should consider to do so when you run into the described issue now and then.&lt;/p&gt;&lt;p&gt;Obviously using private repos will increase the total amount of disk space due to caching the same dependencies in multiple places. Additionally, the first build will take significantly more time because everything has to be downloaded once. However, both consequences are well acceptable given the better stability and isolation of projects.&lt;/p&gt;&lt;p&gt;Instead of clicking the Hudson checkbox for all your projects, you should consider to setup the local Maven repo in your &lt;code&gt;settings.xml&lt;/code&gt; instead. This has a number of advantages:&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;You don't have to setup the option for each and every project, but have it in a central place.&lt;/li&gt;&lt;li&gt;You can use a common root for all local Maven repos, like &lt;code&gt;d:/maven-repo&lt;/code&gt;. This allows you to easily purge all your local repositories from time to time, in order to reduce disk space as well as validate the content (i.e. make sure the build is still running in a clean environment and all required artifacts are in your corporate Maven repository).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;For instance, here is what works fine for us:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;localRepository&amp;gt;d:/builds/.m2/${env.JOB_NAME}/repository&amp;lt;/localRepository&amp;gt;&lt;/pre&gt;&lt;p&gt;This is using a Hudson environment variable (&lt;em&gt;JOB_NAME&lt;/em&gt;) to create subfolders for the actual projects aka jobs. See &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Building+a+software+project"&gt;here&lt;/a&gt; for a list of available variables.&lt;/p&gt;&lt;p&gt;Oh yes, what I suggest is also encouraged by Brian Fox in his &lt;a href="http://www.sonatype.com/people/2009/01/maven-continuous-integration-best-practices/"&gt;Maven Continuous Integration Best Practices&lt;/a&gt; blog post, so you should consider twice to adopt this best practice :o)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-8116423298985213141?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/8116423298985213141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/01/concurrent-builds-with-hudson.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/8116423298985213141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/8116423298985213141'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/01/concurrent-builds-with-hudson.html' title='Concurrent Builds with Hudson'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-5851883396321434211</id><published>2010-01-02T18:24:00.002+01:00</published><updated>2010-01-22T10:24:37.195+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cargo'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><title type='text'>Cargo Maven Plugin: Not Made for JBoss</title><content type='html'>&lt;h4&gt;Again...&lt;/h4&gt;&lt;p&gt;Well, actually this blog was supposed to be about Java in general and all the ups and downs I experience during my daily work. However, I've not been doing much other than Maven configuration and build management lately, so here is another Maven related post. Sorry folks.&lt;/p&gt;&lt;p&gt;As already shown in &lt;a href="http://javamoods.blogspot.com/2009/11/integration-test-with-maven-cargo-and.html"&gt;this post&lt;/a&gt;, I have been doing integration tests with JBoss by using the &lt;a href="http://cargo.codehaus.org/Maven2+plugin"&gt;Cargo Maven plugin&lt;/a&gt; to start the JBoss locally and deploy the application to it. This all works quite as soon as you have figured out how to configure Cargo for JBoss.&lt;/p&gt;&lt;h4&gt;But Remotely Now!&lt;/h4&gt;&lt;p&gt;Now, the next step is to deploy our EAR file which is generated during nightly build to a running JBoss instance on a separate computer. This is different because no JBoss configuration has to be created locally and no JBoss has to be started. Instead, the EAR file must be transferred to a remote server where JBoss is already running, and JBoss must be persuaded to deploy this file.&lt;/p&gt;&lt;p&gt;That sounds feasible, and I've done exactly this before for other servers like Tomcat, so I did not expect any issue here. However, I was wrong.&lt;/p&gt;&lt;h4&gt;Itch #1&lt;/h4&gt;&lt;p&gt;First trouble was caused by my lack of knowledge regarding JBoss. With standard installation, you are not able to connect to the server remotely and all the services are bound to localhost only (see &lt;a href="http://community.jboss.org/wiki/JBoss42FAQ"&gt;here&lt;/a&gt; or &lt;a href="http://community.jboss.org/thread/63800?tstart=0"&gt;here&lt;/a&gt;). This is intentionally, to prevent unprotected installations appearing all over the net. You have to pass the option &lt;code&gt;-b 0.0.0.0&lt;/code&gt; when starting JBoss to allow remote connections to the services, but take care to secure your JBoss accordingly!&lt;/p&gt;&lt;h4&gt;Itch #2&lt;/h4&gt;&lt;p&gt;Okay, after this has been configured, I tried to use Cargo to deploy my EAR file to JBoss. This is the configuration I ended up with:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;!-- *** Cargo plugin: deploy the application to running JBoss *** --&amp;gt;&lt;br /&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;org.codehaus.cargo&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;cargo-maven2-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;configuration&amp;gt;&lt;br /&gt;    &amp;lt;wait&amp;gt;false&amp;lt;/wait&amp;gt;&lt;br /&gt;    &amp;lt;!-- Container configuration --&amp;gt;&lt;br /&gt;    &amp;lt;container&amp;gt;&lt;br /&gt;      &amp;lt;containerId&amp;gt;jboss5x&amp;lt;/containerId&amp;gt;&lt;br /&gt;      &amp;lt;type&amp;gt;remote&amp;lt;/type&amp;gt;&lt;br /&gt;    &amp;lt;/container&amp;gt;&lt;br /&gt;    &amp;lt;!-- Configuration to use with the Container --&amp;gt;&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;      &amp;lt;type&amp;gt;runtime&amp;lt;/type&amp;gt;&lt;br /&gt;      &amp;lt;properties&amp;gt;&lt;br /&gt;        &amp;lt;cargo.hostname&amp;gt;...&amp;lt;/cargo.hostname&amp;gt;&lt;br /&gt;        &amp;lt;cargo.servlet.port&amp;gt;8080&amp;lt;/cargo.servlet.port&amp;gt;&lt;br /&gt;      &amp;lt;/properties&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;&lt;br /&gt;    &amp;lt;!-- Deployer configuration --&amp;gt;&lt;br /&gt;    &amp;lt;deployer&amp;gt;&lt;br /&gt;      &amp;lt;type&amp;gt;remote&amp;lt;/type&amp;gt;&lt;br /&gt;      &amp;lt;deployables&amp;gt;&lt;br /&gt;        &amp;lt;deployable&amp;gt;&lt;br /&gt;          &amp;lt;location&amp;gt;...&amp;lt;/location&amp;gt;&lt;br /&gt;        &amp;lt;/deployable&amp;gt;&lt;br /&gt;      &amp;lt;/deployables&amp;gt;&lt;br /&gt;    &amp;lt;/deployer&amp;gt;&lt;br /&gt;  &amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;executions&amp;gt;&lt;br /&gt;    &amp;lt;execution&amp;gt;&lt;br /&gt;      &amp;lt;id&amp;gt;deploy&amp;lt;/id&amp;gt;&lt;br /&gt;      &amp;lt;phase&amp;gt;deploy&amp;lt;/phase&amp;gt;&lt;br /&gt;      &amp;lt;goals&amp;gt;&lt;br /&gt;        &amp;lt;goal&amp;gt;deployer-redeploy&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;/goals&amp;gt;&lt;br /&gt;    &amp;lt;/execution&amp;gt;&lt;br /&gt;  &amp;lt;/executions&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;/pre&gt;&lt;p&gt;However, I always got this error message:&lt;/p&gt;&lt;pre&gt;[INFO] Failed to deploy to [http://...]&lt;br /&gt;Server returned HTTP response code: 500 for URL: ... &lt;/pre&gt;&lt;p&gt;The configuration seems to be correct, so what is the problem?&lt;/p&gt;&lt;p&gt;After asking Google, I realized that Cargo is not able to transfer a file to JBoss! Instead, it requires the deployable to be deployed to be present on the server filesystem (see &lt;a href="http://markmail.org/message/dzdl2jmsvdlhl7cz#query:cargo%20jboss%20%22Server%20returned%20HTTP%20response%20code%3A%20500%20for%20URL%22+page:1+mid:fnjeuj33223xl74c+state:results"&gt;here&lt;/a&gt;). This is obviously caused by the JBoss JMX deployer which is used by Cargo, but actually you don't care who is to blame &amp;ndash; you just want it to work. The name "Cargo" implies the parcel is transferred to its destination, right? Also note that this &lt;a href="http://jira.codehaus.org/browse/CARGO-416"&gt;issue&lt;/a&gt; is dated from Sep 2006, so there has been some time to fix it in either way.&lt;/p&gt;&lt;h4&gt;What Can We Do?&lt;/h4&gt;&lt;p&gt;Well, there are probably not many options. Since current version of Cargo is not able to transfer the file to the server, you'd have to do this on your own. The location given in our Cargo configuration above actually is the path on the JBoss server. So, when the file exists locally on the JBoss server, Cargo should be able to deploy it successfully.&lt;/p&gt;&lt;p&gt;For transferring the file to JBoss server, we could use the &lt;a href="http://maven.apache.org/plugins/maven-dependency-plugin/"&gt;maven-dependency-plugin&lt;/a&gt;, a quite useful plugin for all kind of analyzing, copying or unpacking artifacts. We configure it to run in pre-integration-test phase and to copy the EAR file (produced by this POM) to some temp directory on the JBoss server:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;maven-dependency-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;executions&amp;gt;&lt;br /&gt;    &amp;lt;execution&amp;gt;&lt;br /&gt;      &amp;lt;id&amp;gt;copy&amp;lt;/id&amp;gt;&lt;br /&gt;      &amp;lt;phase&amp;gt;install&amp;lt;/phase&amp;gt;&lt;br /&gt;      &amp;lt;goals&amp;gt;&lt;br /&gt;        &amp;lt;goal&amp;gt;copy&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;/goals&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;artifactItems&amp;gt;&lt;br /&gt;          &amp;lt;artifactItem&amp;gt;&lt;br /&gt;            &amp;lt;groupId&amp;gt;${project.groupId}&amp;lt;/groupId&amp;gt;&lt;br /&gt;            &amp;lt;artifactId&amp;gt;${project.artifactId}&amp;lt;/artifactId&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;${project.version}&amp;lt;/version&amp;gt;&lt;br /&gt;            &amp;lt;type&amp;gt;${project.packaging}&amp;lt;/type&amp;gt;&lt;br /&gt;            &amp;lt;destFileName&amp;gt;test.ear&amp;lt;/destFileName&amp;gt;&lt;br /&gt;          &amp;lt;/artifactItem&amp;gt;&lt;br /&gt;        &amp;lt;/artifactItems&amp;gt;&lt;br /&gt;        &amp;lt;outputDirectory&amp;gt;${publish.tempdir}&amp;lt;/outputDirectory&amp;gt;&lt;br /&gt;        &amp;lt;overWrite&amp;gt;true&amp;lt;/overWrite&amp;gt;&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;    &amp;lt;/execution&amp;gt;&lt;br /&gt;  &amp;lt;/executions&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;/pre&gt;&lt;p&gt;The property &lt;code&gt;${publish.tempdir}&lt;/code&gt; can be anything on the JBoss server (which must be available in the network!) and is exactly what has to be used for the value of &lt;code&gt;location&lt;/code&gt; element in Cargo configuration.&lt;/p&gt;&lt;p&gt;Another option would be to use the hot-deploy directory of JBoss as &lt;code&gt;outputDirectory&lt;/code&gt; for the dependency plugin, and hence rely on hot deployment of JBoss instead of Cargo and JBoss JMX deployer. This way, we could get rid of Cargo configuration and cleanup the POM a bit, but in the end it seemed a bit less clean to me... your mileage may vary.&lt;/p&gt;&lt;p&gt;So, as always, in the end we got it to work, but not without unforeseen pain. When will Cargo be fixed to get the EAR file to JBoss server? Who knows.&lt;/p&gt;&lt;h4&gt;Updates&lt;/h4&gt;&lt;p&gt;2010/01/22: Note that the dependency plugin must be bound after the &lt;em&gt;install&lt;/em&gt; phase so that the artifact has been copied at least to your local Maven repository. As a consequence, the Cargo plugin must be run in &lt;em&gt;deploy&lt;/em&gt; phase, which is actually a good choice anyways. I have changed this in my code above.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-5851883396321434211?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/5851883396321434211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2010/01/cargo-maven-plugin-not-made-for-jboss.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/5851883396321434211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/5851883396321434211'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2010/01/cargo-maven-plugin-not-made-for-jboss.html' title='Cargo Maven Plugin: Not Made for JBoss'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-1684372365095815778</id><published>2009-12-10T14:10:00.002+01:00</published><updated>2009-12-10T14:16:46.425+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QA'/><category scheme='http://www.blogger.com/atom/ns#' term='Checkstyle'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven Plugins: Upgrade with Care!</title><content type='html'>&lt;h4&gt;Upgrading Maven Plugins: Tips and Issues&lt;/h4&gt;&lt;p&gt;After having shown the list of current Maven plugin versions in my &lt;a href="http://javamoods.blogspot.com/2009/12/maven-plugins-upgrade-with-care.html"&gt;previous post&lt;/a&gt;, now I'm going to share my experiences with upgrading. Just like expected, some of the new plugins did not work out of the box or required some changes in configuration:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;maven-checkstyle-plugin&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;We have used version 2.3 previously which is based on Checkstyle 4.4. In contrast, plugin version 2.4 is eventually built on top of Checkstyle 5 which better supports Java 5 language features (I wrote a &lt;a href="http://javamoods.blogspot.com/2009/05/update-to-checkstyle-50.html"&gt;post&lt;/a&gt; on that issue). The configuration is not fully compatible, so you would have to upgrade it.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;maven-javadoc-plugin&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Starting with version 2.6, JavaDoc plugin can detect the Java API link for the current build. This did not work for us (probably due to missing proxy configuration), so we had to switch it off by setting &lt;em&gt;detectJavaApiLink&lt;/em&gt; property to false. See &lt;a href="http://maven.apache.org/plugins/maven-javadoc-plugin/javadoc-mojo.html"&gt;plugin site&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;taglist-maven-plugin&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The configuration of tags has changed and is now a bit more extensive. Old format (using &lt;em&gt;tags&lt;/em&gt; element) is still supported, but deprecated. See &lt;a href="http://mojo.codehaus.org/findbugs-maven-plugin/2.2/plugin-info.html"&gt;plugin documentation&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;findbugs-maven-plugin&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;I have used version 2.2 which was the most recent one when changing the POM. However, this yielded some strange errors during site generation. This is the strack trace:&lt;/p&gt;&lt;pre&gt;Generating &amp;quot;FindBugs Report&amp;quot; report.&lt;br /&gt;  Plugin Artifacts to be added -&amp;gt;...&lt;br /&gt;  AuxClasspath is -&amp;gt;D:\Profiles\Default User\.m2\repository\org\apache\maven\reporting\maven-reporting-impl\2.0\maven-reporting-impl-2.0.jar;...&lt;br /&gt;[java] Exception in thread &amp;quot;main&amp;quot; java.io.FileNotFoundException: D:\builds\...\User\.m2\repository\...\maven-reporting-impl-2.0.jar;D:\Profiles\Default (The filename, directory name, or volume label syntax is incorrect)&lt;br /&gt;[java]  at java.util.zip.ZipFile.open(Native Method)&lt;br /&gt;[java]  at java.util.zip.ZipFile.&amp;lt;init&amp;gt;(ZipFile.java:114)&lt;br /&gt;[java]  at java.util.zip.ZipFile.&amp;lt;init&amp;gt;(ZipFile.java:131)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.classfile.impl.ZipFileCodeBase.&amp;lt;init&amp;gt;(ZipFileCodeBase.java:53)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.classfile.impl.ZipCodeBaseFactory.countUsingZipFile(ZipCodeBaseFactory.java:92)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.classfile.impl.ZipCodeBaseFactory.makeZipCodeBase(ZipCodeBaseFactory.java:46)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.classfile.impl.ClassFactory.createFilesystemCodeBase(ClassFactory.java:97)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.classfile.impl.FilesystemCodeBaseLocator.openCodeBase(FilesystemCodeBaseLocator.java:75)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.classfile.impl.ClassPathBuilder.processWorkList(ClassPathBuilder.java:564)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.classfile.impl.ClassPathBuilder.build(ClassPathBuilder.java:195)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.FindBugs2.buildClassPath(FindBugs2.java:584)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.FindBugs2.execute(FindBugs2.java:181)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.FindBugs.runMain(FindBugs.java:348)&lt;br /&gt;[java]  at edu.umd.cs.findbugs.FindBugs2.main(FindBugs2.java:1057)&lt;br /&gt;[java] Java Result: 1&lt;/pre&gt;&lt;p&gt;As you can see, we are using Windows default for local Maven repository (&lt;code&gt;D:\Profiles\Default User\.m2&lt;/code&gt;) which obviously is causing a problem with the path later on. How sick is that?!?&lt;/p&gt;&lt;p&gt;Then, after having tried this and that, I discovered there is a brand new version 2.3 available so I tested that one and guess what &amp;ndash; everything works fine again! Hence, don't use version 2.2, it seems to be broken...&lt;/p&gt;&lt;p&gt;&lt;strong&gt;docbkx-maven-plugin&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The latest version of that plugin is 2.0.9, but that did not work correctly. It failed the build with this error:&lt;/p&gt;&lt;pre&gt;ValidationException: null:30:723: Error(30/723): fo:table-body is missing child elements.&lt;br /&gt;Required Content Model: marker* (table-row+|table-cell+)&lt;/pre&gt;&lt;p&gt;The given line/position information did not match to anything suspicious, and I could not see anything wrong in our XSL files. So, no idea what this issue is telling me or what could I do about it. That's why I rolled back to 2.0.8 which just works fine.&lt;/p&gt;&lt;h4&gt;The Bottom Line&lt;/h4&gt;&lt;p&gt;With the given plugin versions, we are up to date again and managed to get rid of some issues hitting us since quite some time. Additionally, we are well prepared for upgrading to Maven 3. I hope I will be able to do so soon, to check if this is really a "&lt;a href="http://www.sonatype.com/people/2009/11/maven-30-alpha-3-released/"&gt;drop-in replacement&lt;/a&gt;"... I will let you know!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-1684372365095815778?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/1684372365095815778/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/12/maven-plugins-upgrade-with-care_10.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1684372365095815778'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1684372365095815778'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/12/maven-plugins-upgrade-with-care_10.html' title='Maven Plugins: Upgrade with Care!'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-7403422408073912953</id><published>2009-12-10T12:21:00.009+01:00</published><updated>2010-01-06T20:28:25.903+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QA'/><category scheme='http://www.blogger.com/atom/ns#' term='Checkstyle'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven Plugins: Current Versions</title><content type='html'>&lt;h4&gt;Upgrading Maven Plugins&lt;/h4&gt;&lt;p&gt;In preparation for a later switch to Maven 3 (which is already &lt;a href="http://old.nabble.com/-ANN--Apache-Maven-3.0-alpha-5-Released-tt26540534.html#a26540534"&gt;knocking on the door&lt;/a&gt;) as well as to get rid of some plugin related issues we are suffering from, I decided to update the Maven plugins we use for build and site generation.&lt;/p&gt;&lt;p&gt;Of course, we are following &lt;a href="http://www.sonatype.com/people/2008/05/optimal-maven-plugin-configuration/"&gt;best practice&lt;/a&gt; and are locking down the version of all plugins in &lt;em&gt;project.build.pluginManagment.plugins&lt;/em&gt; section. This is done in the company's topmost POM, so that all company projects would use the same versions once they reference the latest parent POM.&lt;/p&gt;&lt;p&gt;As you might know, upgrading to new plugin versions is always an adventure and you have to test your builds seriously, which is of course hard when you are going to change the company settings...&lt;/p&gt;&lt;h4&gt;Build Plugins&lt;/h4&gt;&lt;p&gt;Well, here is the list of build plugins we now use with their current version, as well as (in brackets) the version that Maven 3.0-alpha5 defines in its internal POM. I have highlighted where both versions differ:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strike&gt;maven-archetype-plugin: 2.0-alpha-5&lt;/strike&gt; (see comment below)&lt;/li&gt;&lt;li&gt;maven-assembly-plugin: 2.2-beta-4 (2.2-beta-4)&lt;/li&gt;&lt;li&gt;maven-clean-plugin: 2.3 (2.3)&lt;/li&gt;&lt;li&gt;maven-compiler-plugin: 2.0.2 (2.0.2)&lt;/li&gt;&lt;li&gt;maven-dependency-plugin: &lt;strong&gt;2.1&lt;/strong&gt; (2.0)&lt;/li&gt;&lt;li&gt;maven-deploy-plugin: 2.4 (2.4)&lt;/li&gt;&lt;li&gt;maven-ear-plugin: &lt;strong&gt;2.4&lt;/strong&gt; (2.3.1)&lt;/li&gt;&lt;li&gt;maven-ejb-plugin: &lt;strong&gt;2.2&lt;/strong&gt; (2.1)&lt;/li&gt;&lt;li&gt;maven-enforcer-plugin: 1.0-beta-1&lt;/li&gt;&lt;li&gt;maven-help-plugin: 2.1 (2.1)&lt;/li&gt;&lt;li&gt;maven-install-plugin: 2.3 (2.3)&lt;/li&gt;&lt;li&gt;maven-javadoc-plugin: &lt;strong&gt;2.6.1&lt;/strong&gt; (2.5)&lt;/li&gt;&lt;li&gt;maven-jar-plugin: &lt;strong&gt;2.3&lt;/strong&gt; (2.2)&lt;/li&gt;&lt;li&gt;maven-release-plugin: 2.0-beta-9 (2.0-beta-9)&lt;/li&gt;&lt;li&gt;maven-resources-plugin: 2.4.1 (2.4.1)&lt;/li&gt;&lt;li&gt;maven-site-plugin: 2.0.1 (2.0.1)&lt;/li&gt;&lt;li&gt;maven-source-plugin: &lt;strong&gt;2.1.1&lt;/strong&gt; (2.0.4)&lt;/li&gt;&lt;li&gt;maven-surefire-plugin: 2.4.3 (2.4.3)&lt;/li&gt;&lt;li&gt;maven-war-plugin: &lt;strong&gt;2.1-beta-1&lt;/strong&gt; (2.1-alpha-1)&lt;/li&gt;&lt;li&gt;build-helper-maven-plugin: 1.4&lt;/li&gt;&lt;li&gt;failsafe-maven-plugin: 2.4.3-alpha-1&lt;/li&gt;&lt;li&gt;cargo-maven2-plugin: 1.0&lt;/li&gt;&lt;li&gt;docbkx-maven-plugin: 2.0.8&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It's a bit strange that Maven 3.0-alpha5 (which came out end of November) does not use the latest version of all those plugins, most of them having been released before that date. I don't know if this was intentional or not... Let's hope it's not because of unsure quality of latest plugin versions ;-) Anyways, I decided to upgrade to the latest available version for all plugins.&lt;/p&gt;&lt;h4&gt;Reporting Plugins&lt;/h4&gt;&lt;p&gt;Here's the list for plugins related to site reports:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;cobertura-maven-plugin: 2.3&lt;/li&gt;&lt;li&gt;findbugs-maven-plugin: 2.3&lt;/li&gt;&lt;li&gt;jdepend-maven-plugin: 2.0-beta-2&lt;/li&gt;&lt;li&gt;maven-checkstyle-plugin: 2.4&lt;/li&gt;&lt;li&gt;maven-jxr-plugin: 2.1&lt;/li&gt;&lt;li&gt;maven-pmd-plugin: 2.4&lt;/li&gt;&lt;li&gt;maven-project-info-reports-plugin: 2.1.2&lt;/li&gt;&lt;li&gt;maven-surefire-report-plugin: 2.4.3&lt;/li&gt;&lt;li&gt;taglist-maven-plugin: 2.4&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I'm going to show some tips and issues when upgrading to these versions in an upcoming post...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-7403422408073912953?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/7403422408073912953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/12/maven-plugins-upgrade-with-care.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7403422408073912953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7403422408073912953'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/12/maven-plugins-upgrade-with-care.html' title='Maven Plugins: Current Versions'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-440026712526735113</id><published>2009-12-02T08:51:00.020+01:00</published><updated>2010-02-18T15:45:57.396+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Unit and Integration Testing with Maven, Part 2</title><content type='html'>&lt;h4&gt;Welome Back...&lt;/h4&gt;&lt;p&gt;... to the second installment of this little series. After having seen the requirements and hassles when using Maven for testing in the &lt;a href="http://javamoods.blogspot.com/2009/11/unit-and-integration-testing-with-maven.html"&gt;last post&lt;/a&gt;, we are now going to list the possible solutions.&lt;/p&gt;&lt;p&gt;Remember, Maven does support different phases for unit and integration tests, but there is &lt;em&gt;only one&lt;/em&gt; source directory (usually &lt;code&gt;src/test/java&lt;/code&gt;), making it a bit difficult to setup and organize test environments. Hence, we have to use some way to separate both types of test.&lt;/p&gt;&lt;h4&gt;Option 1: Separate Module for Integration Tests&lt;/h4&gt;&lt;p&gt;In case you are using modules for your project anyways and want to have integration tests which are testing these modules in integration, this is the natural solution: just create another module that depends on the other ones and only contains the integration test sources and resources.&lt;/p&gt;&lt;p&gt;However, if you instead want to integration-test each module individually, this approach just doubles the number of modules, which can be difficult to manage. You could put all integration tests into one big module &amp;ndash; but that has other disadvantages, of course.&lt;/p&gt;&lt;p&gt;Since we do not have any sources (only test sources) in that integration-test project, the usual build lifecycle would execute a lot of unneeded steps like copying resources, compiling, testing, creating JAR file etc. We could use the POM packaging type to suppress all of this, but then we have to configure the maven-compiler-plugin to force compilation of test sources.&lt;/p&gt;&lt;p&gt;Independantly of packaging type, we have to do some more configurations:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Execute Surefire plugin in &lt;em&gt;integration-test&lt;/em&gt; phase.&lt;/li&gt;&lt;li&gt;Prepare integration tests (for instance, start the container and deploy the application) in &lt;em&gt;pre-integration-test&lt;/em&gt; phase. This is quite easy with &lt;a href="http://cargo.codehaus.org/Maven2+plugin"&gt;Cargo Maven plugin&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Shutdown integration tests (stop the container) in &lt;em&gt;post-integration-test&lt;/em&gt; phase.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Here is the relevant part of such a POM file:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Compiler plugin: we must force test compile because we're using a &lt;br /&gt;             pom packaging that doesn't have this lifecycle mapping. --&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;          &amp;lt;goals&amp;gt;&lt;br /&gt;            &amp;lt;goal&amp;gt;testCompile&amp;lt;/goal&amp;gt;&lt;br /&gt;          &amp;lt;/goals&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;      &amp;lt;/executions&amp;gt;&lt;br /&gt;    &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Surefire plugin: run integration tests *** --&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;          &amp;lt;phase&amp;gt;integration-test&amp;lt;/phase&amp;gt;&lt;br /&gt;          &amp;lt;goals&amp;gt;&lt;br /&gt;            &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;&lt;br /&gt;          &amp;lt;/goals&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;      &amp;lt;/executions&amp;gt;&lt;br /&gt;    &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Cargo plugin: start/stop application server and deploy the ear &lt;br /&gt;             file before/after integration tests *** --&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;org.codehaus.cargo&amp;lt;/groupId&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;cargo-maven2-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;       ...&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;br /&gt;      &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;!-- before integration tests are run: start server --&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;          &amp;lt;id&amp;gt;start-container&amp;lt;/id&amp;gt;&lt;br /&gt;          &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;&lt;br /&gt;          &amp;lt;goals&amp;gt;&lt;br /&gt;            &amp;lt;goal&amp;gt;start&amp;lt;/goal&amp;gt;&lt;br /&gt;          &amp;lt;/goals&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;        &amp;lt;!-- after integration tests are run: stop server --&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;          &amp;lt;id&amp;gt;stop-container&amp;lt;/id&amp;gt;&lt;br /&gt;          &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;&lt;br /&gt;          &amp;lt;goals&amp;gt;&lt;br /&gt;            &amp;lt;goal&amp;gt;stop&amp;lt;/goal&amp;gt;&lt;br /&gt;          &amp;lt;/goals&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;      &amp;lt;/executions&amp;gt;&lt;br /&gt;    &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt;&amp;lt;/build&amp;gt;&lt;/pre&gt;&lt;h4&gt;Option 2: Different Source Directories&lt;/h4&gt;&lt;p&gt;In this scenario, unit and integration test sources are placed in separate source directories, like &lt;code&gt;src/test/java&lt;/code&gt; and &lt;code&gt;src/integrationtest/java&lt;/code&gt;. I think this would definitely be the best solution, and it actually should be what Maven supports out of the box. Sadly, Maven does not, and as far as I know Maven 3 won't either :-(&lt;/p&gt;&lt;p&gt;Well, we should be able to configure things this way. For compiling and executing integration tests, you would have to configure Compiler plugin to compile the integration test sources in pre-integration-test phase (using the &lt;a href="http://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#includes"&gt;includes parameter&lt;/a&gt;), and then configure a second Surefire execution using &lt;a href="http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html#testClassesDirectory"&gt;testClassesDirectory parameter&lt;/a&gt; to point it to the integration test folder.&lt;/p&gt;&lt;p&gt;However, this option seems a bit fragile to me. Even if it works (I haven't checked), the integration test folder would probably not show up in Eclipse when using m2eclipse plugin and other plugins may have issues with this additional test source path as well. That's why I do not recommend this option.&lt;/p&gt;&lt;h4&gt;Option 3: Different File Name Patterns&lt;/h4&gt;&lt;p&gt;In this scenario, the package or file name is used to distinguish between unit and integration test source files. Let's say, for instance, that all integration test classes start with &lt;em&gt;IT*&lt;/em&gt; and hence the filename pattern is &lt;code&gt;**/IT*.java&lt;/code&gt;. We'd have to configure the Surefire plugin to execute twice: once in test phase for executing the unit tests only, and another time in integration-test phase to execute, well, the integration tests (and only those)&lt;/p&gt;&lt;p&gt;A common way to do so is this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;In configuration of Surefire plugin, set &lt;code&gt;skip&lt;/code&gt; parameter to true to bypass all tests.&lt;/li&gt;&lt;li&gt;Add an &lt;code&gt;execution&lt;/code&gt; element for unit tests, where &lt;code&gt;skip&lt;/code&gt; is set to false and &lt;code&gt;exclude&lt;/code&gt; parameter is used to exclude the integration tests.&lt;/li&gt;&lt;li&gt;Add another &lt;code&gt;execution&lt;/code&gt; element for integration tests, where &lt;code&gt;skip&lt;/code&gt; is set to false and &lt;code&gt;include&lt;/code&gt; parameter is used to just include the integration tests and nothing else.&lt;/li&gt;&lt;li&gt;Prepare and shutdown of integration tests are like before.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Here is the POM section:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Surefire plugin: run unit and integration tests in &lt;br /&gt;             separate lifecycle phases, using file name pattern *** --&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;skip&amp;gt;true&amp;lt;/skip&amp;gt;&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;      &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;          &amp;lt;id&amp;gt;unit-test&amp;lt;/id&amp;gt;&lt;br /&gt;          &amp;lt;phase&amp;gt;test&amp;lt;/phase&amp;gt;&lt;br /&gt;          &amp;lt;goals&amp;gt;&lt;br /&gt;            &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;&lt;br /&gt;          &amp;lt;/goals&amp;gt;&lt;br /&gt;          &amp;lt;configuration&amp;gt;&lt;br /&gt;            &amp;lt;skip&amp;gt;false&amp;lt;/skip&amp;gt;&lt;br /&gt;            &amp;lt;excludes&amp;gt;&lt;br /&gt;              &amp;lt;exclude&amp;gt;**/IT*.java&amp;lt;/exclude&amp;gt;&lt;br /&gt;            &amp;lt;/excludes&amp;gt;&lt;br /&gt;          &amp;lt;/configuration&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;          &amp;lt;id&amp;gt;integration-test&amp;lt;/id&amp;gt;&lt;br /&gt;          &amp;lt;phase&amp;gt;integration-test&amp;lt;/phase&amp;gt;&lt;br /&gt;          &amp;lt;goals&amp;gt;&lt;br /&gt;            &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;&lt;br /&gt;          &amp;lt;/goals&amp;gt;&lt;br /&gt;          &amp;lt;configuration&amp;gt;&lt;br /&gt;            &amp;lt;skip&amp;gt;false&amp;lt;/skip&amp;gt;&lt;br /&gt;            &amp;lt;includes&amp;gt;&lt;br /&gt;              &amp;lt;include&amp;gt;**/IT*.java&amp;lt;/include&amp;gt;&lt;br /&gt;            &amp;lt;/includes&amp;gt;&lt;br /&gt;          &amp;lt;/configuration&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;      &amp;lt;/executions&amp;gt;&lt;br /&gt;    &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Cargo plugin: start/stop application server and deploy the ear &lt;br /&gt;             file before/after integration tests *** --&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt;&amp;lt;/build&amp;gt;&lt;/pre&gt;&lt;p&gt;There is another approach to achieve the same result:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;In configuration of Surefire plugin, use the &lt;code&gt;exclude&lt;/code&gt; parameter to exclude the integration tests when executing unit tests in test phase.&lt;/li&gt;&lt;li&gt;Add an &lt;code&gt;execution&lt;/code&gt; element for integration tests, where &lt;code&gt;exclude&lt;/code&gt; is set to any dummy value (to override the default configuration) and &lt;code&gt;include&lt;/code&gt; parameter is used to just include the integration tests and nothing else.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;It's a bit shorter than the former configuration, but in the end it's a matter of taste. Again, here is the POM snippet:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Surefire plugin: run unit and integration tests in &lt;br /&gt;             separate lifecycle phases, using file name pattern *** --&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;excludes&amp;gt;&lt;br /&gt;          &amp;lt;exclude&amp;gt;**/IT*.java&amp;lt;/exclude&amp;gt;&lt;br /&gt;        &amp;lt;/excludes&amp;gt;&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;      &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;          &amp;lt;id&amp;gt;integration-test&amp;lt;/id&amp;gt;&lt;br /&gt;          &amp;lt;phase&amp;gt;integration-test&amp;lt;/phase&amp;gt;&lt;br /&gt;          &amp;lt;goals&amp;gt;&lt;br /&gt;            &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;&lt;br /&gt;          &amp;lt;/goals&amp;gt;&lt;br /&gt;          &amp;lt;configuration&amp;gt;&lt;br /&gt;            &amp;lt;excludes&amp;gt;&lt;br /&gt;              &amp;lt;exclude&amp;gt;none&amp;lt;/exclude&amp;gt;&lt;br /&gt;            &amp;lt;/excludes&amp;gt;&lt;br /&gt;            &amp;lt;includes&amp;gt;&lt;br /&gt;              &amp;lt;include&amp;gt;**/IT*.java&amp;lt;/include&amp;gt;&lt;br /&gt;            &amp;lt;/includes&amp;gt;&lt;br /&gt;          &amp;lt;/configuration&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;      &amp;lt;/executions&amp;gt;&lt;br /&gt;    &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Cargo plugin: start/stop application server and deploy the ear &lt;br /&gt;             file before/after integration tests *** --&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt;&amp;lt;/build&amp;gt;&lt;/pre&gt;&lt;h4&gt;Failsafe Plugin&lt;/h4&gt;&lt;p&gt;Instead of using the Surefire plugin with custom filename pattern to distinguish between unit and integration test classes, you should rather use the &lt;a href="http://mojo.codehaus.org/failsafe-maven-plugin/"&gt;Failsafe plugin&lt;/a&gt; for executing integration tests.&lt;/p&gt;&lt;p&gt;This plugin is a fork of the Surefire plugin designed to run integration tests. &lt;br /&gt;It is used during the &lt;code&gt;integration-test&lt;/code&gt; and &lt;code&gt;verify&lt;/code&gt; phases of the build lifecycle to execute the integration tests of an application. Other than Surefire plugin, the Failsafe plugin will not fail the build when executing tests thus enabling the post-integration-test phase to execute.&lt;/p&gt;&lt;p&gt;Failsafe plugin has its own naming convention. By default, the Surefire plugin executes &lt;code&gt;**/Test*.java&lt;/code&gt;, &lt;code&gt;**/*Test.java&lt;/code&gt;, and &lt;code&gt;**/*TestCase.java&lt;/code&gt; test classes. In contrast, the Failsafe plugin will look for &lt;code&gt;**/IT*.java&lt;/code&gt;, &lt;code&gt;**/*IT.java&lt;/code&gt;, and &lt;code&gt;**/*ITCase.java&lt;/code&gt;. Did you note that this matches what we used before for our integration tests? ;-)&lt;/p&gt;&lt;p&gt;When using Failsafe, the last POM (of option 3) looks like this:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Surefire plugin: run unit and exclude integration tests *** --&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;excludes&amp;gt;&lt;br /&gt;          &amp;lt;exclude&amp;gt;**/IT*.java&amp;lt;/exclude&amp;gt;&lt;br /&gt;        &amp;lt;/excludes&amp;gt;&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;    &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Failsafe plugin: run integration tests *** --&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;failsafe-maven-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;version&amp;gt;2.4.3-alpha-1&amp;lt;/version&amp;gt;&lt;br /&gt;      &amp;lt;executions&amp;gt;&lt;br /&gt;        &amp;lt;execution&amp;gt;&lt;br /&gt;          &amp;lt;goals&amp;gt;&lt;br /&gt;            &amp;lt;goal&amp;gt;integration-test&amp;lt;/goal&amp;gt;&lt;br /&gt;            &amp;lt;goal&amp;gt;verify&amp;lt;/goal&amp;gt;&lt;br /&gt;          &amp;lt;/goals&amp;gt;&lt;br /&gt;        &amp;lt;/execution&amp;gt;&lt;br /&gt;      &amp;lt;/executions&amp;gt;&lt;br /&gt;    &amp;lt;/plugin&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;!-- *** Cargo plugin: start/stop application server and deploy the ear &lt;br /&gt;             file before/after integration tests *** --&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt;&amp;lt;/build&amp;gt;&lt;/pre&gt;&lt;p&gt;Of course, Failsafe would also work with first option (separate integration test module).&lt;/p&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;&lt;p&gt;Well, after having shown all the ways that came into my mind, here are my personal "best practices":&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Use the Failsafe plugin to execute integration tests.&lt;/li&gt;&lt;li&gt;If keeping integration tests in a separate module feels alright, do so (see option 1).&lt;/li&gt;&lt;li&gt;If you want to have unit and integration tests in the same module, choose a file or package name pattern to distinguish between both, and configure Surefire and Failsafe plugins accordingly.&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Update (2010/02/18)&lt;/h4&gt;&lt;p&gt;Note that there is a new version 2.5 of failsafe plugin available with changed group id: &lt;code&gt;org.apache.maven.plugins:maven-failsafe-plugin:2.5&lt;/code&gt;. See the &lt;a href="http://maven.apache.org/plugins/maven-failsafe-plugin/index.html"&gt;plugin site&lt;/a&gt; for details. Thanks to stug23 for pointing that out!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-440026712526735113?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/440026712526735113/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/12/unit-and-integration-testing-with-maven.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/440026712526735113'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/440026712526735113'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/12/unit-and-integration-testing-with-maven.html' title='Unit and Integration Testing with Maven, Part 2'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-4620580064584636064</id><published>2009-11-28T17:39:00.007+01:00</published><updated>2009-11-28T18:32:15.250+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Unit and Integration Testing with Maven, Part 1</title><content type='html'>&lt;h4&gt;Test Types&lt;/h4&gt;&lt;p&gt;In my &lt;a href="http://javamoods.blogspot.com/2009/11/integration-test-with-maven-cargo-and.html"&gt;last post&lt;/a&gt;, I talked about integration testing with Maven's Cargo plugin and JBoss Application Server. Now let's see how integration testing fits into an overall testing strategy with Maven.&lt;/p&gt;&lt;p&gt;When thinking about tests and testing strategies, there is one important thing to keep in mind: integration tests are not unit tests (even though JUnit may be used to write integration tests). For the sake of completeness, let's pin down the main characteristics of both:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Unit Tests:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;are testing a small piece of code in isolation&lt;/li&gt;&lt;li&gt;are independant from other tests&lt;/li&gt;&lt;li&gt;are usually written by software developers&lt;/li&gt;&lt;li&gt;have to be very fast because they are run quite often&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In contrast, &lt;strong&gt;Integration Tests:&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;individual software modules are combined and tested as a group&lt;/li&gt;&lt;li&gt;are usually much slower than unit tests because a context has to be established (Spring, database, web server etc.)&lt;/li&gt;&lt;li&gt;normally are run after unit testing&lt;/li&gt;&lt;li&gt;may be created by QA team using tools, but also by developers using JUnit test cases (which still does not turn them into unit tests)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Testing with Maven&lt;/h4&gt;&lt;p&gt;As you know, &lt;a href="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html"&gt;Maven Build Lifecycle&lt;/a&gt; provides phases both for testing and integration testing. Related phases are:&lt;/p&gt;&lt;pre&gt;...&lt;br /&gt;generate-test-sources&lt;br /&gt;generate-test-resources&lt;br /&gt;process-test-resources&lt;br /&gt;test-compile&lt;br /&gt;process-test-classes&lt;br /&gt;test&lt;br /&gt;...&lt;br /&gt;pre-integration-test&lt;br /&gt;integration-test&lt;br /&gt;post-integration-test&lt;br /&gt;...&lt;/pre&gt;&lt;p&gt;Unfortunately, Maven does not support separate source directories for both test types. This is really complicating things (as we'll see in a minute). There have been &lt;a href="http://docs.codehaus.org/display/MAVEN/Testing+Strategies"&gt;some discussions&lt;/a&gt; on how to fix that, but I don't think it made it into &lt;a href="http://www.sonatype.com/people/2009/11/maven-3x-paving-the-desire-lines-part-one-2/"&gt;Maven 3&lt;/a&gt; (not quite sure, though).&lt;/p&gt;&lt;p&gt;Hence, what we need to have is this:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Both unit and integration tests have to be compiled by javac.&lt;/li&gt;&lt;li&gt;Nevertheless, they should be clearly separated from each other by a path or file name pattern.&lt;/li&gt;&lt;li&gt;Unit tests have to be run in &lt;code&gt;test&lt;/code&gt; lifecycle phase, and the build should stop if they do not succeed.&lt;/li&gt;&lt;li&gt;Integration tests should be run in &lt;code&gt;integration-test&lt;/code&gt; phase, and at least the &lt;code&gt;post-integration-test&lt;/code&gt; phase has to be run independantly of test result (to be able to shutdown a running container, close database connections etc.).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The next part of this small series will show how these requirements can be met with Maven and what has to be configured, so please stand by...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-4620580064584636064?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/4620580064584636064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/11/unit-and-integration-testing-with-maven.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4620580064584636064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4620580064584636064'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/11/unit-and-integration-testing-with-maven.html' title='Unit and Integration Testing with Maven, Part 1'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-949985339967990482</id><published>2009-11-27T17:22:00.017+01:00</published><updated>2009-11-27T21:39:03.995+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cargo'/><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><title type='text'>Integration test with Maven, Cargo and JBoss</title><content type='html'>&lt;h4&gt;It's Friday...&lt;/h4&gt;&lt;p&gt;... and I thought it would be a good idea to setup an integration test of some EJBs we are creating in a new project. Actually, it was not, since it nearly ruined my evening. But eventually I got it to work, and here is how.&lt;/p&gt;&lt;p&gt;To test the EJBs, I need to create an EAR file, deploy that to the application server (JBoss 5.1.0 in our case) and run JUnit test cases against this server. For Maven, I have setup a separate &lt;code&gt;integration-test&lt;/code&gt; module for executing the integration test for the following reasons:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;to better separate unit tests (with JUnit) from integration tests (also with JUnit), which simplifies Maven configuration a bit.&lt;/li&gt;&lt;li&gt;to be able to run this module outside of the normal CI (continuous integration) build due to its lack of performance.&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Cargo Maven Plugin&lt;/h4&gt;&lt;p&gt;For automatically starting the container, deploying the EAR file and stopping the container when the tests are finished, I use the &lt;a href="http://cargo.codehaus.org/Maven2+plugin"&gt;Cargo Maven plugin&lt;/a&gt;. I did this several times before (with Tomcat, though) &amp;ndash; so I thought that'd be easy...&lt;/p&gt;&lt;p&gt;Well, when using JBoss, there are some tricks you have to know. Before going into the details, some more information on Cargo.&lt;/p&gt;&lt;p&gt;A &lt;em&gt;Container&lt;/em&gt; is the base concept in Cargo. It represents an existing application server runtime, and Cargo hides all the details of the actual server implementation for you. There are two types of containers:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Local Container&lt;/em&gt;: this is executing on the machine where Cargo runs. This can either be an &lt;em&gt;Installed Container&lt;/em&gt; which is, well, installed on the local machine and is run in a separate VM, or an &lt;em&gt;Embedded Container&lt;/em&gt; that is executing in the same JVM where Cargo is running (currently only supported for Jetty).&lt;/li&gt;&lt;li&gt;&lt;em&gt;Remote Container&lt;/em&gt;: a container that is already running anywhere (local or remote). It's not under Cargo's control and can't be started or stopped by Cargo.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;You use a &lt;em&gt;Configuration&lt;/em&gt; to specify how the container is configured (logging, data sources, location where to put the deployables, etc). The available configuration depends on the container type:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;em&gt;Local Configuration&lt;/em&gt;: for local containers. There are two local configuration types: &lt;em&gt;Standalone Local Configuration&lt;/em&gt; which configures the container from scratch in a directory of your choice, and &lt;em&gt;Existing Local Configuration&lt;/em&gt; that re-uses an existing container installation already residing on your hard drive.&lt;/li&gt;&lt;li&gt;&lt;em&gt;Runtime Configuration&lt;/em&gt;: You use a runtime configuration when you want to access your container as a black box through a remote protocol (JMX, etc). This is perfect for remote containers.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In my case, I wanted to use a Local Installed Container with a Standalone Local Configuration, to eliminate dependencies from other deployments.&lt;/p&gt;&lt;h4&gt;JBoss with Cargo&lt;/h4&gt;&lt;p&gt;Well, and here are the pitfalls when using JBoss in this setting:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Experimental:&lt;/strong&gt; JBoss 5.x is still an &lt;a href="http://cargo.codehaus.org/JBoss+5.x"&gt;experimental container&lt;/a&gt; for Cargo. This is a bit strange given the fact that this version is now out for a while, but fortunately not really an issue.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Extensive Logging:&lt;/strong&gt; When Cargo builds the JBoss configuration &amp;ndash; remember, I use Standalone Local Configuration so Cargo creates one from scratch &amp;ndash; it uses a logging setup (independantly from what is used with your JBoss installation!) that is way too chatty. The console scrolls forever, and things are slowing down in a way that you think everything is stuck in an infinite loop.&lt;br&gt;Thus, you have to tell Cargo to use another logging configuration file, which is a bit tricky and not documented very well (see &lt;a href="http://jira.codehaus.org/browse/CARGO-585"&gt;this issue&lt;/a&gt;).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Shutdown Port:&lt;/strong&gt; Now the container starts up, the tests are run, but after that JBoss AS is not shutting down. It's telling me &lt;code&gt;javax.naming.CommunicationException: Could not obtain connection to any of these urls: localhost:1299&lt;/code&gt;, which means the &lt;a href="http://article.gmane.org/gmane.comp.java.cargo.user/1381"&gt;wrong port&lt;/a&gt; is used for shutdown. Standard shutdown port is 1099, so we have to tell Cargo to use that port number.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;All in all, the configuration now looks like this. Mentioned settings are highlighted. Perhaps this is useful for someone else...&lt;/p&gt;&lt;pre class="brush:xml; highlight: [23,33,34,35,36,37,38,39,40]"&gt;&lt;br /&gt;&amp;lt;!-- *** Cargo plugin: start/stop JBoss application server and deploy the ear &lt;br /&gt;         file before/after integration tests *** --&amp;gt;&lt;br /&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;org.codehaus.cargo&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;cargo-maven2-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;configuration&amp;gt;&lt;br /&gt;    &amp;lt;wait&amp;gt;false&amp;lt;/wait&amp;gt;&lt;br /&gt;    &amp;lt;!-- Container configuration --&amp;gt;&lt;br /&gt;    &amp;lt;container&amp;gt;&lt;br /&gt;      &amp;lt;containerId&amp;gt;jboss5x&amp;lt;/containerId&amp;gt;&lt;br /&gt;      &amp;lt;type&amp;gt;installed&amp;lt;/type&amp;gt;&lt;br /&gt;      &amp;lt;home&amp;gt;${it.jboss5x.home}&amp;lt;/home&amp;gt;&lt;br /&gt;      &amp;lt;timeout&amp;gt;300000&amp;lt;/timeout&amp;gt;&lt;br /&gt;    &amp;lt;/container&amp;gt;&lt;br /&gt;    &amp;lt;!-- Configuration to use with the Container --&amp;gt;&lt;br /&gt;    &amp;lt;configuration&amp;gt;&lt;br /&gt;      &amp;lt;type&amp;gt;standalone&amp;lt;/type&amp;gt;&lt;br /&gt;      &amp;lt;home&amp;gt;${project.build.directory}/jboss5x&amp;lt;/home&amp;gt;&lt;br /&gt;      &amp;lt;properties&amp;gt;&lt;br /&gt;        &amp;lt;cargo.jboss.configuration&amp;gt;default&amp;lt;/cargo.jboss.configuration&amp;gt;&lt;br /&gt;        &amp;lt;cargo.servlet.port&amp;gt;${it.jboss5x.port}&amp;lt;/cargo.servlet.port&amp;gt;&lt;br /&gt;        &amp;lt;cargo.rmi.port&amp;gt;1099&amp;lt;/cargo.rmi.port&amp;gt;&lt;br /&gt;        &amp;lt;cargo.jvmargs&amp;gt;-Xmx512m&amp;lt;/cargo.jvmargs&amp;gt;&lt;br /&gt;      &amp;lt;/properties&amp;gt;&lt;br /&gt;      &amp;lt;deployables&amp;gt;&lt;br /&gt;        &amp;lt;deployable&amp;gt;&lt;br /&gt;          &amp;lt;groupId&amp;gt;com.fja.ipl&amp;lt;/groupId&amp;gt;&lt;br /&gt;          &amp;lt;artifactId&amp;gt;ipl-lc-ear&amp;lt;/artifactId&amp;gt;&lt;br /&gt;          &amp;lt;type&amp;gt;ear&amp;lt;/type&amp;gt;&lt;br /&gt;        &amp;lt;/deployable&amp;gt;&lt;br /&gt;      &amp;lt;/deployables&amp;gt;&lt;br /&gt;      &amp;lt;!-- Override logging created by Cargo (which is way to chatty) with default &lt;br /&gt;           file from JBoss (see http://jira.codehaus.org/browse/CARGO-585) --&amp;gt;&lt;br /&gt;      &amp;lt;configfiles&amp;gt;&lt;br /&gt;        &amp;lt;configfile&amp;gt;&lt;br /&gt;          &amp;lt;file&amp;gt;src/test/resources/jboss-log4j.xml&amp;lt;/file&amp;gt;&lt;br /&gt;          &amp;lt;todir&amp;gt;conf&amp;lt;/todir&amp;gt;&lt;br /&gt;        &amp;lt;/configfile&amp;gt;&lt;br /&gt;      &amp;lt;/configfiles&amp;gt;&lt;br /&gt;    &amp;lt;/configuration&amp;gt;&lt;br /&gt;  &amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;executions&amp;gt;&lt;br /&gt;    &amp;lt;!-- before integration tests are run: start server --&amp;gt;&lt;br /&gt;    &amp;lt;execution&amp;gt;&lt;br /&gt;      &amp;lt;id&amp;gt;start-container&amp;lt;/id&amp;gt;&lt;br /&gt;      &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;&lt;br /&gt;      &amp;lt;goals&amp;gt;&lt;br /&gt;        &amp;lt;goal&amp;gt;start&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;/goals&amp;gt;&lt;br /&gt;    &amp;lt;/execution&amp;gt;&lt;br /&gt;    &amp;lt;!-- after integration tests are run: stop server --&amp;gt;&lt;br /&gt;    &amp;lt;execution&amp;gt;&lt;br /&gt;      &amp;lt;id&amp;gt;stop-container&amp;lt;/id&amp;gt;&lt;br /&gt;      &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;&lt;br /&gt;      &amp;lt;goals&amp;gt;&lt;br /&gt;        &amp;lt;goal&amp;gt;stop&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;/goals&amp;gt;&lt;br /&gt;    &amp;lt;/execution&amp;gt;&lt;br /&gt;  &amp;lt;/executions&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;br /&gt;&amp;lt;properties&amp;gt;&lt;br /&gt;  &amp;lt;it.jboss5x.home&amp;gt;${basedir}/../../../tools/bin/jboss-5.1.0.GA&amp;lt;/it.jboss5x.home&amp;gt;&lt;br /&gt;  &amp;lt;it.jboss5x.port&amp;gt;8080&amp;lt;/it.jboss5x.port&amp;gt;&lt;br /&gt;&amp;lt;/properties&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-949985339967990482?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/949985339967990482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/11/integration-test-with-maven-cargo-and.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/949985339967990482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/949985339967990482'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/11/integration-test-with-maven-cargo-and.html' title='Integration test with Maven, Cargo and JBoss'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-269391471108899594</id><published>2009-11-19T09:47:00.012+01:00</published><updated>2009-11-19T11:44:20.890+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JEE'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><title type='text'>JBoss and Maven</title><content type='html'>&lt;h4&gt;The Challenge&lt;/h4&gt;&lt;p&gt;During the last days I was busy trying to build and deploy a JEE application on JBoss &amp;ndash; using Maven, of course. One interesting task was to run integration tests, i.e. JUnit tests that are testing a service bean deployed on JBoss application server. Integration tests with Maven are an interesting issue, worth its own blog entry probably. But this post is all about JBoss.&lt;/p&gt;&lt;p&gt;Well, this task doesn't sound hard for a Maven expert, but unexpectedly it was not that easy. Our test code (calling the EJB) was depending on JBoss artifacts, which might be questionable in itself but that's how it's currently done. Hence, during runtime the code needs the &lt;code&gt;jbossall-client.jar&lt;/code&gt; from JBoss' client directory in the classpath.&lt;/p&gt;&lt;h4&gt;The Eclipse Way&lt;/h4&gt;&lt;p&gt;We are using JBoss 5.x, and in this version the &lt;code&gt;jbossall-client.jar&lt;/code&gt; is rather small since it only references all required jar files in the Manifest's Class-Path element:&lt;/p&gt;&lt;pre class="brush:java;"&gt;Manifest-Version: 1.0&lt;br /&gt;Specification-Title: JBossAS&lt;br /&gt;Specification-Version: 5.0.0.GA&lt;br /&gt;...&lt;br /&gt;Implementation-Vendor: JBoss.org&lt;br /&gt;Implementation-Vendor-Id: http://www.jboss.org/&lt;br /&gt;Class-Path: commons-logging.jar concurrent.jar ejb3-persistence.jar hi&lt;br /&gt; bernate-annotations.jar jboss-aop-client.jar jboss-appclient.jar jbos&lt;br /&gt; s-aspect-jdk50-client.jar jboss-client.jar jboss-common-core.jar jbos&lt;br /&gt; s-deployers-client-spi.jar jboss-deployers-client.jar jboss-deployers&lt;br /&gt; -core-spi.jar jboss-deployers-core.jar jboss-deployment.jar jboss-ejb&lt;br /&gt; 3-common-client.jar jboss-ejb3-core-client.jar jboss-ejb3-ext-api.jar&lt;br /&gt;  jboss-ejb3-proxy-clustered-client.jar jboss-ejb3-proxy-impl-client.j&lt;br /&gt; ar jboss-ejb3-proxy-spi-client.jar jboss-ejb3-security-client.jar jbo&lt;br /&gt; ss-ha-client.jar jboss-ha-legacy-client.jar jboss-iiop-client.jar jbo&lt;br /&gt; ss-integration.jar jboss-j2se.jar jboss-javaee.jar jboss-jsr77-client&lt;br /&gt; .jar jboss-logging-jdk.jar jboss-logging-log4j.jar jboss-logging-spi.&lt;br /&gt; jar jboss-main-client.jar jboss-mdr.jar jboss-messaging-client.jar jb&lt;br /&gt; oss-remoting.jar jboss-security-spi.jar jboss-serialization.jar jboss&lt;br /&gt; -srp-client.jar jboss-system-client.jar jboss-system-jmx-client.jar j&lt;br /&gt; bosscx-client.jar jbossjts-integration.jar jbossjts.jar jbosssx-as-cl&lt;br /&gt; ient.jar jbosssx-client.jar jmx-client.jar jmx-invoker-adaptor-client&lt;br /&gt; .jar jnp-client.jar slf4j-api.jar slf4j-jboss-logging.jar xmlsec.jar&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This list is impressive... and the approach is working with current Eclipse. The equivalent for the Maven world would be a POM that references all other required libraries as normal dependencies (see &lt;a href="http://markmail.org/message/snk2p6sssulo3s25#query:jbossall-client.jar%20now%20references%20external%20libs+page:1+mid:dh3rmeex7iib7z2x+state:results"&gt;this&lt;/a&gt; discussion).&lt;/p&gt;&lt;h4&gt;The Maven Way&lt;/h4&gt;&lt;p&gt;And yes, such a POM &lt;code&gt;org.jboss.jbossas:jboss-as-client&lt;/code&gt; is available on &lt;a href="http://repository.jboss.com/maven2/org/jboss/jbossas/jboss-as-client"&gt;JBoss Maven repository&lt;/a&gt; (note: it's not &lt;code&gt;org.jboss.client:jbossall-client&lt;/code&gt; which is the reference-by-manifest's-class-path version!).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;However, this approach involves two issues:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;By following the dependencies defined in this &lt;code&gt;org.jboss.client:jbossall-client&lt;/code&gt; transitively, Maven will download a vast number of JBoss and JEE libraries which you actually don't want to be used and packaged in your client. This includes things like &lt;code&gt;org.jboss.jbossas:jboss-as-server:jar:5.1.0.GA&lt;/code&gt; and &lt;code&gt;jacorb:jacorb:jar:2.3.0jboss.patch6-brew&lt;/code&gt;. Does not sound confidence-building, does it? Seems like JBoss should exclude transitive dependencies at the right places.&lt;/li&gt;&lt;li&gt;Moreover, some of the dependencies can't be found on any of the Maven repositories we configured to proxy in our Nexus. This includes Maven Central, JBoss of course, and a couple of others, so I do not know what else to add to provide the missing jars. Maybe it's just that the reference itself is wrong (version number?).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Instead of excluding everything we do not use currently, next idea is to just include those dependencies to the JBoss jar files that the client actually requires. But... it's quite hard to find out the corresponding Maven coordinates. This includes guessing the groupd and artifact id, but also the version &amp;ndash; and unfortunately the version information given in the jar's manifest file is not useful since it notes the JBoss AS version instead of the version of the library which is required for Maven.&lt;/p&gt;&lt;h4&gt;Lost in Space?&lt;/h4&gt;&lt;p&gt;So, I ended up re-packaging a jar that holds the content of the required client jars and putting this on our Nexus...&lt;/p&gt;&lt;p&gt;I honestly wonder how everybody else is using JBoss 5.x with Maven on the client side???&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-269391471108899594?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/269391471108899594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/11/jboss-and-maven.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/269391471108899594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/269391471108899594'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/11/jboss-and-maven.html' title='JBoss and Maven'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-5669565895318765077</id><published>2009-11-13T08:02:00.004+01:00</published><updated>2009-11-13T08:30:13.640+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OSGi'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Spring dm Server Considered Cool?</title><content type='html'>&lt;h4&gt;w-jax is over...&lt;/h4&gt;&lt;p&gt;I'm just returning from &lt;a href="http://it-republik.de/jaxenter/wjax09/"&gt;w-jax 2009&lt;/a&gt;, one of the biggest german Java conferences, covering every technology related to Java actually.&lt;/p&gt;&lt;p&gt;If there are any hypes this year, they are these: Scala, Cloud Computing and OSGi. And, of course, Spring &amp;#150; which is all around.&lt;/p&gt;&lt;p&gt;Spring Source employs a lot of brave guys, and hearing first-hand about their newest coolest technologies is always refreshing. Did you know that Tomcat is to a large extent pushed by guys paid by Spring Source? I forgot the exact number, but &lt;a href="http://jandiandme.blogspot.com/"&gt;Eberhard Wolff&lt;/a&gt; said the majority of bug fixes and commits is done by Spring Source's Tomcat team.&lt;/p&gt;&lt;h4&gt;Spring dm Server is Cool!&lt;/h4&gt;&lt;p&gt;There have been some sessions about &lt;a href="http://www.springsource.com/products/dmserver"&gt;Spring dm Server&lt;/a&gt;, and when taking a closer look it seems to be clear why Spring Source invests in Tomcat that much. Spring dm server is based on Tomcat, and they add the ability to deploy web application modules as OSGi bundles. This way, you can partition your web apps into separate bundles to deploy them independantly and dynamically into the server. Yes, they are preserving OSGi's dynamic, meaning that you can stop, start or refresh a particular bundle without the need to stop and restart the server. As you would expect, other bundles continue to work. If a requested OSGi service is temporarily not available, dm Server will wait 5 minutes for it being redeployed.&lt;/p&gt;&lt;p&gt;Spring dm server is part of &lt;a href="http://www.springsource.com/products/sts"&gt;Spring Tool Suite&lt;/a&gt;, an Eclipse based development environment which is also able to auto-deploy a module whenever it changes.&lt;/p&gt;&lt;p&gt;All of this is quite gorgeous from a technical perspective, and the Spring guys had to cope with some really hard issues (for instance, realted to JPA where they need an application wide visiblity of bundles as well as load time weaving &amp;#150; you won't want to know the details...).&lt;/p&gt;&lt;h4&gt;Really? What for?&lt;/h4&gt;&lt;p&gt;But... is this really of any interest in the field?&lt;/p&gt;&lt;p&gt;Our customers are using WebSphere (or WebLogic or maybe JBoss) application server, and all of them are not capable of running such a modularized, OSGi based application. Moreover, in a production environment, there is no need and most often it is actually not even desired to be able to refresh application bundles dynamically.&lt;/p&gt;&lt;p&gt;So, what's left? Modularizing your application? Right, that is leading to a better structure and less coupling and blah blah, but the same can be achieved without OSGi (just let the business domain drive your application "slices"). It's just that you are &lt;em&gt;forced&lt;/em&gt; to use modules (bundles) when you are using OSGi.&lt;/p&gt;&lt;p&gt;If at all, Spring dm server will pay off for developers since it may speed up development (especially the build-deploy-test cycle). But is this really, I mean really, hurting us that much? Hence, if you were asking me, a lot of technical overhead and server lock-in for no real benefit.&lt;/p&gt;&lt;p&gt;So, will Spring dm server be able to gain real attention, I mean beyond being technically cool? I'm sceptical. As always, time will tell...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-5669565895318765077?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/5669565895318765077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/11/spring-dm-server-considered-cool.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/5669565895318765077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/5669565895318765077'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/11/spring-dm-server-considered-cool.html' title='Spring dm Server Considered Cool?'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-7187117966946657541</id><published>2009-10-27T08:47:00.008+01:00</published><updated>2009-10-27T10:45:21.664+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='oAW'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Java Mystery: Directory Exists but Does Not?</title><content type='html'>&lt;p&gt;Well, yesterday for me was another one of those days where you think your computer must be fooling you... There is an issue with a DirectoryCleaner that works for a subproject but does not when called from the parent. But first things first.&lt;/p&gt;&lt;h4&gt;The openArchitectureWare Part&lt;/h4&gt;&lt;p&gt;We are using oAW (yep, the new version which is part of &lt;a href="http://www.eclipse.org/modeling/"&gt;Eclipse Modeling Project&lt;/a&gt; of Eclipse Galileo). Before generating the artifacts from the model, we are executing a directory cleaner that just rubs out the folders, for instance &lt;code&gt;src/generated/java&lt;/code&gt;. The workflow file &lt;code&gt;generate.mwe&lt;/code&gt; looks like this:&lt;/p&gt;&lt;pre class="brush:java; highlight: [3]"&gt;&amp;lt;workflow&amp;gt;&lt;br /&gt;   &amp;lt;property file=&amp;quot;generateAll.properties&amp;quot;/&amp;gt;&lt;br /&gt;   &amp;lt;component class='org.eclipse.emf.mwe.utils.DirectoryCleaner' directory='${srcGenDir}'/&amp;gt;&lt;br /&gt;   &amp;lt;component file='.../generateAll.mwe' inheritAll=&amp;quot;true&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;modelFile value='...' /&amp;gt;&lt;br /&gt;   &amp;lt;/component&amp;gt;&lt;br /&gt;&amp;lt;/workflow&amp;gt;&lt;/pre&gt;&lt;p&gt;&lt;code&gt;srcGenDir&lt;/code&gt; is a property that is defined in the included properties file, but that's irrelevant. The highlighted line configures the mentioned directory cleaner. The relevant code snippet is &lt;code&gt;invokeInternal()&lt;/code&gt; method of &lt;code&gt;org.eclipse.emf.mwe.utils.DirectoryCleaner&lt;/code&gt; which is part of Eclipse EMF frameworks:&lt;/p&gt;&lt;pre class="brush:java"&gt;protected void invokeInternal(final WorkflowContext model, &lt;br /&gt;                 final ProgressMonitor monitor, final Issues issues) {&lt;br /&gt;   if (directory != null) {&lt;br /&gt;      final StringTokenizer st = new StringTokenizer(directory, &amp;quot;,&amp;quot;);&lt;br /&gt;      while (st.hasMoreElements()) {&lt;br /&gt;         final String dir = st.nextToken().trim();&lt;br /&gt;         final File f = new File(dir);&lt;br /&gt;         if (f.exists() &amp;amp;&amp;amp; f.isDirectory()) {&lt;br /&gt;            ... do the cleanup ...&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Pretty simple, right? The &lt;code&gt;directory&lt;/code&gt; attribute contains one or more directories (comma separated), hence a tokenizer is used to get each of them and to create a file. If this file exists and it's a directory, that will be erased.&lt;/p&gt;&lt;h4&gt;The Maven Part&lt;/h4&gt;&lt;p&gt;Of course we are using Maven to build the stuff. The &lt;a href="http://fornax.itemis.de/confluence/display/fornax/OAW-M2-Plugin+%28TOM%29"&gt;Fornax Maven plugin&lt;/a&gt; is configured to call the workflow during Maven build. Moreover, the mentioned workflow is part of a subproject B which belongs to an outer multi-module project A.&lt;/p&gt;&lt;p&gt;Now, this is where the mystery begins... When I build B (the submodule), everything is fine and works like expected. However, when I build A (the parent project), B will be built in turn and its workflow is executed, but the directory is &lt;em&gt;not&lt;/em&gt; cleaned up! You wouldn't expect this, right?&lt;/p&gt;&lt;h4&gt;The Strange Part&lt;/h4&gt;&lt;p&gt;In an attempt to find out what's going on, we put some debugging code into &lt;code&gt;DirectoryCleaner&lt;/code&gt;. It turns out that the file &lt;code&gt;f&lt;/code&gt; returns the same value for &lt;code&gt;getAbsolutePath()&lt;/code&gt; in both cases, but &lt;code&gt;f.exists()&lt;/code&gt; reveals &lt;code&gt;false&lt;/code&gt; when the build is started from the parent project &amp;ndash; hence the condition is not met and nothing will be cleaned up.&lt;/p&gt;&lt;p&gt;Unfortunately, you can't look any deeper into the native code that is called when determining if a file exists. So, in a kind of trial and error approach, we found out that using the following code fixes the issue:&lt;/p&gt;&lt;pre class="brush:java; highlight: [8]"&gt;protected void invokeInternal(final WorkflowContext model, &lt;br /&gt;                 final ProgressMonitor monitor, final Issues issues) {&lt;br /&gt;   if (directory != null) {&lt;br /&gt;      final StringTokenizer st = new StringTokenizer(directory, &amp;quot;,&amp;quot;);&lt;br /&gt;      while (st.hasMoreElements()) {&lt;br /&gt;         final String dir = st.nextToken().trim();&lt;br /&gt;         final File f1 = new File(dir);&lt;br /&gt;         final File f = new File(f1.getAbsolutePath());&lt;br /&gt;         if (f.exists() &amp;amp;&amp;amp; f.isDirectory()) {&lt;br /&gt;            ... do the cleanup ...&lt;br /&gt;         }&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;That is: by creating another file that is using the absolute path of the first one and using this further on, everything is fine in both scenarios &amp;ndash; whether called from parent project or submodule.&lt;/p&gt;&lt;p&gt;To be honest: I have no explanation for these findings. Why is &lt;code&gt;File&lt;/code&gt; behaving differently? When calculating the exist flag, the code should take into account the file's absolute path, right? So, why is creation of another file based on the absolute path is fixing the issue? Any insights are deeply appreciated...!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-7187117966946657541?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/7187117966946657541/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/10/java-mystery-directory-exists-but-does.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7187117966946657541'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7187117966946657541'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/10/java-mystery-directory-exists-but-does.html' title='Java Mystery: Directory Exists but Does Not?'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-2023431757575732558</id><published>2009-10-16T13:37:00.012+02:00</published><updated>2009-10-16T15:16:13.535+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><title type='text'>Speeding Up Your System</title><content type='html'>&lt;p&gt;We did a lot of interesting stuff lately, including upgrading Eclipse to the new &lt;a href="http://www.eclipse.org/galileo/"&gt;Galileo&lt;/a&gt; release, and in turn upgrading oAW (&lt;a href="http://www.openarchitectureware.org/"&gt;openArchitectureware&lt;/a&gt;) to the new versions of Xtext, Xpand, Xcheck etc. which are now part of the &lt;a href="http://www.eclipse.org/modeling/"&gt;Eclipse Modeling project&lt;/a&gt;. I will blog about all this later...&lt;/p&gt;&lt;p&gt;But, what really started to hurt us was the performance of our Windows XP based development laptops. They aren't really brand new ones, but not that old either. Nevertheless, they seem to have an issue with all those java, class and jar files involved when starting Eclipse, doing a "Clean Project", when using Maven to build the software etc.&lt;/p&gt;&lt;p&gt;IT department was not willing to provide us with new hardware (disk especially) at this time, and no, using Linux is no option either. Hence, we had to find out other areas of improvement by tuning our system.&lt;/p&gt;&lt;p&gt;Here is what we did to speed things up for Windows XP. Note that things might or might not be different for Windows Vista or Windows 7.&lt;/p&gt;&lt;h4&gt;1. Disable Indexing Service&lt;/h4&gt;&lt;p&gt;By default, there is a Microsoft "Indexing Service" running in your Windows system. According to &lt;a href="http://msdn.microsoft.com/en-us/library/ms689718(VS.85).aspx"&gt;msdn&lt;/a&gt;, this is "a base service for Microsoft Windows 2000 or later that extracts content from files and constructs an indexed catalog to facilitate efficient and rapid searching."&lt;/p&gt;&lt;p&gt;Well, to be honest, I have never heard of that service before (and rarely use the search function of Windows), but it turned out to cause lots of harddisk traffic. So we decided to &lt;strong&gt;disable this service&lt;/strong&gt;, which is recommended &lt;a href="http://www.blackviper.com/WinXP/Services/Indexing_Service.htm"&gt;by some people&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Actually, there are several ways to do so (wihtout using Microsoft Management Console (MMC) with an appropriate snap-in):&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Disable the Indexing Service in your list of local services.&lt;/li&gt;&lt;li&gt;In the Properties window of your local disk, remove option "Allow Indexing Service to index this disk for fast file searching".&lt;/li&gt;&lt;li&gt;Remove the function via the Control Panel &gt; Add or Remove Programs &gt; Add/Remove Windows Components &gt; Uncheck "Indexing Service".&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;2. Don't Virus-Scan Java Stuff&lt;/h4&gt;&lt;p&gt;Our anti-virus tool was configured to scan literally everything, including java, class and jar files. This seems to be exaggerated from security point of view, but IT folks said they could not configure the anti-virus to ignore a particular set of file extensions (like *.jar).&lt;/p&gt;&lt;p&gt;Hence, what we did instead was to &lt;strong&gt;exclude two folders from being scanned on the fly&lt;/strong&gt;: &lt;code&gt;javatools&lt;/code&gt; (where everything Java related is put, including Eclipse releases) and &lt;code&gt;projects&lt;/code&gt; (where all our projects reside). Instead, these folders are now scanned once a week, which is acceptable for IT guys.&lt;/p&gt;&lt;p&gt;Know what? That speeded up starting time of Eclipse  &lt;em&gt;by factor 5&lt;/em&gt;!&lt;/p&gt;&lt;p&gt;Surprisingly, excluding the Maven local repository (located in your personal settings folder) from being scanned on the fly did not make much difference, so we didn't handle this folder any special.&lt;/p&gt;&lt;h4&gt;3. Optimize Subversion&lt;/h4&gt;&lt;p&gt;Are you using Subversion? If so, are you using &lt;a href="http://tortoisesvn.tigris.org/"&gt;TortoiseSVN&lt;/a&gt;, the Windows Shell Extension for Subversion? Well, in that case you will know and probably like the little overlay icons that are used to indicate the state of files and folders. This feature is recursive, whereby overlay changes in lower level folders are propagated up through the folder hierarchy so that you don’t forget about changes you made deep in the tree.&lt;/p&gt;&lt;p&gt;Starting with &lt;a href="http://tortoisesvn.tigris.org/tsvn_1.2_releasenotes.html"&gt;release 1.2&lt;/a&gt;, a new TSVNCache program is used to maintain a cache of your working copy status, providing much faster access to this information. Not only does this prevent explorer from blocking while acquiring status, but it also makes recursive overlays workable.&lt;/p&gt;&lt;p&gt;This is all nice, but there is a major drawback: TSVNCache by default looks for changes &lt;em&gt;on all drives and in all folders&lt;/em&gt;, killing disk performance with all the I/O it's doing.&lt;/p&gt;&lt;p&gt;You can &lt;strong&gt;enable a TSVNCacheWindow&lt;/strong&gt; showing all the folders being crawled by TSVNCache. To do so, open the Registry Editor, and create a new &lt;code&gt;DWORD&lt;/code&gt; at &lt;code&gt;HKEY_CURRENT_USER\Software\TortoiseSVN\CacheTrayIcon&lt;/code&gt; with value of 1. After that you have to restart TSVNCache which is easiest done by just killing the process, it will be automatically restarted when you do any TortoiseSVN operation. Now there should be a small tortoise icon in Windows tray area which opens the TSVNCacheWindow. Watch how TortoiseSVN scans files and folders whenever you write to a file...&lt;/p&gt;&lt;p&gt;Time to fix that! That should be quite easy if you're keeping all of your working copies below one specific folder (or a small set of folders), like we do. All you have to do is to &lt;strong&gt;setup TortoiseSVN to only scan your sourcefolder paths&lt;/strong&gt;:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Right-click in Explorer on any folder and select "TortoiseSVN &gt; Settings...".&lt;/li&gt;&lt;li&gt;In the Settings window's tree, click on the "Icon Overlays" entry.&lt;/li&gt;&lt;li&gt;In the "Exclude Paths" input field, put C:\* to exclude the entire C drive. If you have more drives, exclude them all at the top level. Use newlines to separate the values.&lt;/li&gt;&lt;li&gt;In the "Include Paths" input field, list all of the locations where your working copies are stored, again separated by newlines.&lt;/li&gt;&lt;li&gt;Switch off "Network drives" option in "Drive Types" area.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;All in all, your settings should now look like in the following screenshot. Thanks to &lt;a href="http://www.paraesthesia.com/archive/2007/09/26/optimize-tortoise-svn-cache-tsvncache.exe-disk-io.aspx"&gt;Paraesthesia&lt;/a&gt; for this nice tip!&lt;/p&gt;&lt;a href="http://4.bp.blogspot.com/_ey2D_DPIY5E/SthxumZXYPI/AAAAAAAAACY/nDwNAML5xSw/s1600-h/TortoiseSvnSettings.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 264px;" src="http://4.bp.blogspot.com/_ey2D_DPIY5E/SthxumZXYPI/AAAAAAAAACY/nDwNAML5xSw/s400/TortoiseSvnSettings.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5393185599171027186" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4&gt;Epilogue&lt;/h4&gt;&lt;p&gt;You won't believe what difference these three little tunings made to our system performance. The harddisk is not any more busy all the time, applications (like Eclipse) are starting much faster, and build time has decreased drastically. Not bad for not spending anything on new hardware! Well, next thing we will check is what effect a new (big, fast) hard disk will have...  ;o)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-2023431757575732558?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/2023431757575732558/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/10/speeding-up-your-system.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2023431757575732558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2023431757575732558'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/10/speeding-up-your-system.html' title='Speeding Up Your System'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_ey2D_DPIY5E/SthxumZXYPI/AAAAAAAAACY/nDwNAML5xSw/s72-c/TortoiseSvnSettings.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-9127569869769629632</id><published>2009-09-18T08:30:00.005+02:00</published><updated>2009-09-18T09:56:44.027+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><title type='text'>Spring: Use Custom Namespaces!</title><content type='html'>&lt;p&gt;Have you ever heard of custom XML namespaces for Spring? I know you love Spring (like I do), so... probably yes. They are available since Spring 2.0 which came out October 2006, so I just can't believe we didn't use them up to now.&lt;/p&gt;&lt;h4&gt;The Old-Fashioned Way&lt;/h4&gt;&lt;p&gt;Well, we are building our web apps on JSF and Spring Web Flow, and additionally use a custom framework for adding a few more features like mapping between business objects and view objects based on XML mapping descriptions. Of course, this framework part is designed "IoC friendly", i.e. it's based on interfaces and standard implementations that need to be plugged by Spring configuration.&lt;/p&gt;&lt;p&gt;We did this by providing a basic Spring configuration that defines defaults for most elements and injects all required references into the main configuration objects. To allow the project to provide custom implementations, this code relies on particular bean names that have to be defined by the custom project. Here's a simple example for the framework's configuration:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;bean id="iplIntegrationInfo" class="...IntegrationInfo"&amp;gt;&lt;br /&gt;  &amp;lt;!-- myViewObjAccessor: to be defined in project specific Spring config file --&amp;gt;&lt;br /&gt;  &amp;lt;property name="viewObjAccessor" ref="myViewObjAccessor" /&amp;gt;&lt;br /&gt;  &amp;lt;!-- myContextResolver: to be defined in project specific Spring config file --&amp;gt;&lt;br /&gt;  &amp;lt;property name="contextResolver" ref="myContextResolver" /&amp;gt;&lt;br /&gt;  ...&lt;br /&gt;&amp;lt;/bean&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- These can be used for aliases if standard implementation should be used --&amp;gt;&lt;br /&gt;&amp;lt;bean id="defaultViewObjAccessor" class="..." /&amp;gt;&lt;br /&gt;&amp;lt;bean id="defaultContextResolver" class="..." /&amp;gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;As you can see, all references are injected into the main configuration (iplIntegrationInfo). However, the referenced beans are not actually defined but have to be provided by the project. So, here's an example for the project's configuration:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;!-- use default --&amp;gt;&lt;br /&gt;&amp;lt;alias alias="myViewObjAccessor" name="defaultViewObjAccessor" /&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;!-- use custom implementation --&amp;gt;&lt;br /&gt;&amp;lt;bean id="myContextResolver" class="..." /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Here we use the default for the first bean (by just establishing an alias for the configuration done in the framework file), and a custom implementation for the second.&lt;/p&gt;&lt;p&gt;This approach works, but obviously has a few drawbacks:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Configuration is shared between framework and project specific configuration code.&lt;/li&gt;&lt;li&gt;Project needs to know the framework's Spring file to do its work.&lt;/li&gt;&lt;li&gt;Internal framework structures (bean names, classes) are exposed to the outside.&lt;/li&gt;&lt;li&gt;A lot of XML code is required, even if using all the defaults.&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Using Custom Namespaces&lt;/h4&gt;&lt;p&gt;What should I say, we have switched to custom namespace lately and now configuration looks like this:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;ui:view-config/&amp;gt;&lt;/pre&gt;&lt;p&gt;That's as short as it can be, but still is a complete configuration in case the project is using default implementations for all the beans. If the project would like to override some settings, the configuration file may be:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;ui:view-config&amp;gt;&lt;br /&gt;  &amp;lt;ui:viewobj-accessor ref="viewObjAccessor"/&amp;gt;&lt;br /&gt;  &amp;lt;ui:context-resolver ref="contextResolver"/&amp;gt;&lt;br /&gt;&amp;lt;/ui:view-config&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;bean id="viewObjAccessor" class="..." /&amp;gt;&lt;br /&gt;&amp;lt;bean id="contextResolver" class="..." /&amp;gt;&lt;/pre&gt;&lt;p&gt;Hence, you have the option to override all default implementations, and use meaningful tags to do so. Can you see the gains?&lt;/p&gt;&lt;h4&gt;How Does This Magic Work?&lt;/h4&gt;&lt;p&gt;I'm not going to provide full description on how to author custom namespaces since that is available in the &lt;a href="http://static.springsource.org/spring/docs/2.5.x/reference/extensible-xml.html"&gt;Spring reference documentation&lt;/a&gt; and &lt;a href="http://www.theserverside.com/tt/articles/article.tss?l=CustomNamespacesSpring2"&gt;elsewhere&lt;/a&gt;. So, just a few basics to give you the idea...&lt;/p&gt;&lt;p&gt;First of all, you have to provide an XML schema describing your namespace. Then you have to implement a &lt;em&gt;Namespace Handler&lt;/em&gt; that links each tag of your namespace to an XML parser, the &lt;em&gt;Bean Definition Parser&lt;/em&gt;. And then, of course, those parsers must be implemented.&lt;/p&gt;&lt;p&gt;Each bean defintion parser is supposed to parse the XML element (including all attributes and sub elements) and to build the appropriate Spring beans. Spring provides a small hierarchy of classes you can use, depending on your situation:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;The most specific is &lt;code&gt;AbstractSimpleBeanDefinitionParser&lt;/code&gt; that fits well when there is a strong correlation between the attributes on a tag and the properties on your bean. In this case, there is really few code on your side.&lt;/li&gt;&lt;li&gt;The &lt;code&gt;AbstractSingleBeanDefinitionParser&lt;/code&gt; is a bit more general, it allows you to create any single bean definition for an arbitrary complex nested XML structure. This involves more coding, of course, but still does some work for you (like automatically registering the bean in the context). This is the one you'll probably use most of the time.&lt;/li&gt;&lt;li&gt;The &lt;code&gt;AbstractBeanDefinitionParser&lt;/code&gt; is even more general and allows you to create multiple bean definitions and register them directly. It takes care of id generation and a few other things.&lt;/li&gt;&lt;li&gt;Instead of using the latter one, you could also implement the &lt;code&gt;BeanDefinitionParser&lt;/code&gt; interface directly, giving you all the flexibility you need.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;All in all, you'll need a few hours to get comfortable with all the classes that are used to build up the bean definitions (&lt;code&gt;DomUtils&lt;/code&gt;, &lt;code&gt;BeanDefinition&lt;/code&gt;, &lt;code&gt;BeanDefinitionBuilder&lt;/code&gt;, &lt;code&gt;RuntimeBeanReference&lt;/code&gt; and &lt;code&gt;ManagedMap&lt;/code&gt;/&lt;code&gt;ManagedList&lt;/code&gt; to name a few).&lt;/p&gt;But after that, building the parser and creating/registering your beans is quite straightforward. Moreover, you always can sneak a peek on how Spring itself is doing it for the Spring provided custom namespaces (like for Spring Security, for instance). &lt;p&gt;&lt;/p&gt;&lt;p&gt;Okay, that's all for now, so go ahead and make life easier for your customers, your team, or yourself by providing a well-designed custom Spring namespace!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-9127569869769629632?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/9127569869769629632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/09/spring-use-custom-namespaces.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/9127569869769629632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/9127569869769629632'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/09/spring-use-custom-namespaces.html' title='Spring: Use Custom Namespaces!'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-839015811173650292</id><published>2009-09-08T11:31:00.003+02:00</published><updated>2009-09-08T11:59:44.656+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Testing'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='JUnit'/><title type='text'>Spring: Test Framework Never Heard of Web Apps?</title><content type='html'>Do you know the &lt;a href="http://static.springsource.org/spring/docs/2.5.6/reference/testing.html"&gt;Spring TestContext Framework&lt;/a&gt;? You really should. It drastically simplifies JUnit-testing of Spring powered applications. One particular cool thing is that it offers an easy, annotation based way to load your Spring context and auto-wire your beans. For example, this is how it could look like for JUnit 4: &lt;p&gt;&lt;/p&gt;&lt;pre class="brush:java"&gt;@RunWith(SpringJUnit4ClassRunner.class)&lt;br /&gt;@ContextConfiguration(locations = "classpath:spring-config/ui-test-config.xml")&lt;br /&gt;public class MyParticularTest {&lt;br /&gt;  @Autowired&lt;br /&gt;  private Controller controller;&lt;br /&gt;  ...&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;This is really nice, but... there is one thing we stumbled upon lately.&lt;/p&gt;&lt;p&gt;The test framework by default is using the &lt;code&gt;GenericXmlContextLoader&lt;/code&gt; which loads the Spring application context as an instance of &lt;code&gt;GenericApplicationContext&lt;/code&gt;. This class, obviously, is not aware of web applications that would require a &lt;code&gt;WebApplicationContext&lt;/code&gt; instead. Hence, you can't access any web related resources, use associated scopes etc.&lt;/p&gt;&lt;p&gt;Don't get me wrong... Spring TestContext Framework is nice, but it's more than strange that it does not support the web scenario. There is a &lt;a href="http://jira.springframework.org/browse/SPR-5243"&gt;Jira issue&lt;/a&gt; for that, but it's still open for more than 10 months now, and is scheduled not until Spring 3.1?!? That's just annoying.&lt;/p&gt;&lt;p&gt;Well, there are some workarounds of course, based on using a custom context loader. See &lt;a href="http://codinghood.blogspot.com/2009/01/spring-integration-testing-for-web.html"&gt;this blog post&lt;/a&gt; or &lt;a href="http://forum.springsource.org/showthread.php?t=62533&amp;amp;page=2"&gt;this Spring community thread&lt;/a&gt;, for instance.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-839015811173650292?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/839015811173650292/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/09/spring-test-framework-never-heard-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/839015811173650292'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/839015811173650292'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/09/spring-test-framework-never-heard-of.html' title='Spring: Test Framework Never Heard of Web Apps?'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-6261008650878593123</id><published>2009-09-08T09:53:00.006+02:00</published><updated>2009-09-08T10:32:47.093+02:00</updated><title type='text'>Highlight your Syntax</title><content type='html'>&lt;p&gt;Now, summer is nearly over and I'm back on this blog. During summer time, I use to spend more time with my family (and doing vacation ;-) but now my head is full with lots of snippets that could make it into this blog.&lt;/p&gt;&lt;p&gt;First of all, I have integrated some syntax highlighting to these pages. This might be well-known and boring for you, but I didn't really know how to do this until finding Alex Gorbatchev's &lt;a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter"&gt;SyntaxHighlighter&lt;/a&gt;. It's purely based on JavaScript and hence can be easily integrated with lots of products, tools and engines – like Blogger.com. Integration couldn't be easier, see &lt;a href="http://mlawire.blogspot.com/2009/07/blogger-syntax-highlighting.html"&gt;here&lt;/a&gt; for a step-by-step explanation. &lt;/p&gt;&lt;p&gt;When adding code, you just have to give your &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; element a class like this: &lt;code&gt;&amp;lt;pre class="brush:java"&amp;gt;&lt;/code&gt;. That's it!&lt;br /&gt;&lt;br /&gt;What do you get by this? Well, the well-known, nicely formatted code blocks like this one&lt;/p&gt;&lt;pre class="brush:java; highlight: [7]"&gt;public void prepareMethodOverrides() throws BeanDefinitionValidationException {&lt;br /&gt;   // Check that lookup methods exists.&lt;br /&gt;   MethodOverrides methodOverrides = getMethodOverrides();&lt;br /&gt;   if (!methodOverrides.isEmpty()) {&lt;br /&gt;      for (Iterator it = methodOverrides.getOverrides().iterator(); it.hasNext(); ) {&lt;br /&gt;         MethodOverride mo = (MethodOverride) it.next();&lt;br /&gt;         prepareMethodOverride(mo);&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This works for lots of languages (called "brushes"), including XML and JavaScript, and you can easily provide a custom brush. Standard layout can be customized, of course, but the default is pretty good IMO.&lt;/p&gt;&lt;p&gt;There are just two or three things (there is always room for improvements ;-)&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Syntax Highlighter documentation is a bit sparse...&lt;/li&gt;&lt;li&gt;The server hosting the CSS and JavaScript files, &lt;code&gt;http://alexgorbatchev.com&lt;/code&gt;, seems to be not the fastest one. To speed up things, the Syntax Highlighter files could be hosted somewhere else, and they most probably already are.&lt;/li&gt;&lt;li&gt;You can highlight particular lines using the &lt;code&gt;&amp;lt;pre class="brush:java; highlight: [14, 15]"&amp;gt;&lt;/code&gt; syntax (see line 7 in example above). However, it seems you can't specify areas but have to list all individual lines which might be cumbersome.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;All in all, pretty cool. Syntax Highlighter is open source under LGPL 3, but the author asks you to "buy him a beer" if you use his tool. Well, I honestly will think of some donation ;-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-6261008650878593123?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/6261008650878593123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/09/highlight-your-syntax.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/6261008650878593123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/6261008650878593123'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/09/highlight-your-syntax.html' title='Highlight your Syntax'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-4419370443599774526</id><published>2009-06-23T15:25:00.011+02:00</published><updated>2009-09-08T09:51:06.941+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven: How Relocated Artifacts Can Ruin Your Day</title><content type='html'>&lt;p&gt;Wow, this is one of those days I struggle with issues all the time without actually going forward one little bit on my original task... I guess you all know this feeling :o(&lt;/p&gt;&lt;p&gt;Now, one of the things that I wasted quite some time on is excluding a dependency. One of our modules is defining a dependency to &lt;a href="http://commons.apache.org/dbcp/"&gt;Apache DBCP&lt;/a&gt; framework like this: &lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;commons-dbcp&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;commons-dbcp&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1.2.1&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;p&gt;This dependency is transitively depending on some XML artifacts, which you can see by using the &lt;a href="http://maven.apache.org/plugins/maven-dependency-plugin/"&gt;maven-dependency-plugin&lt;/a&gt;'s tree goal:&lt;/p&gt;&lt;pre class="brush:xml; highlight: [4,5]"&gt;...&lt;br /&gt;[INFO] +- commons-dbcp:commons-dbcp:jar:1.2.1:compile&lt;br /&gt;[INFO]   +- commons-pool:commons-pool:jar:1.2:compile&lt;br /&gt;[INFO]   +- xml-apis:xml-apis:jar:1.0.b2:compile&lt;br /&gt;[INFO]   \- xerces:xercesImpl:jar:2.0.2:compile&lt;br /&gt;...&lt;/pre&gt;&lt;p&gt;Well, the xml-apis and xerces artifacts are a bit outdated and actually we didn't want them at all in our war files, so I decided to exclude them using the &lt;a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html"&gt;dependency exclusion&lt;/a&gt; feature:&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;commons-dbcp&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;commons-dbcp&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1.2.1&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;exclusions&amp;gt;&lt;br /&gt;    &amp;lt;exclusion&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;xml-apis&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;xml-apis&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;/exclusion&amp;gt;&lt;br /&gt;    &amp;lt;exclusion&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;xerces&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;xercesImpl&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;/exclusion&amp;gt;&lt;br /&gt;  &amp;lt;/exclusions&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;p&gt;What do you think will be the result? Surprisingly, &lt;code&gt;xml-apis:xml-apis&lt;/code&gt; vanished, but &lt;code&gt;xerces:xercesImpl&lt;/code&gt; didn't. The new dependency tree is the evidence:&lt;/p&gt;&lt;pre class="brush:xml; highlight: [4]"&gt;...&lt;br /&gt;[INFO] +- commons-dbcp:commons-dbcp:jar:1.2.1:compile&lt;br /&gt;[INFO]   +- commons-pool:commons-pool:jar:1.2:compile&lt;br /&gt;[INFO]   \- xerces:xercesImpl:jar:2.0.2:compile&lt;br /&gt;...&lt;/pre&gt;&lt;p&gt;That's strange, isn't it? It took me an hour or so playing around to find the reason for this behaviour: &lt;strong&gt;Xerces has been relocated&lt;/strong&gt; with respect to its Maven coordinates... The only hint Maven is giving you is this message when executing in debug mode:&lt;/p&gt;&lt;pre class="brush:xml"&gt;[DEBUG] While downloading xerces:xerces:2.0.2&lt;br /&gt;  This artifact has been relocated to xerces:xercesImpl:2.0.2.&lt;/pre&gt;&lt;p&gt;What does that mean? Well, you may relocate artifacts in the Maven repository when the group or artifact id should change (for more details, see the &lt;a href="http://maven.apache.org/guides/mini/guide-relocation.html"&gt;Guide to Relocation&lt;/a&gt;). Originally, the DBCP artifact specified a dependency to &lt;code&gt;xerces:xerces&lt;/code&gt; in its dependencies – which you can see in the artifact's POM file (residing in your local Maven cache, for instance):&lt;/p&gt;&lt;pre class="brush:xml"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;xerces&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;xerces&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;2.0.2&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;p&gt;However, &lt;code&gt;xerces:xerces&lt;/code&gt; has been relocated to &lt;code&gt;xerces:xercesImpl&lt;/code&gt; and these new coordinates are what is shown in the dependency tree. But, when excluding a dependency, you must specify the original transitive dependency (as defined by the artifact), not the new coordinates:&lt;/p&gt;&lt;pre class="brush:xml; highlight: [11,12]"&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;commons-dbcp&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;commons-dbcp&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1.2.1&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;exclusions&amp;gt;&lt;br /&gt;    &amp;lt;exclusion&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;xml-apis&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;xml-apis&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;/exclusion&amp;gt;&lt;br /&gt;    &amp;lt;exclusion&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;xerces&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;xerces&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;/exclusion&amp;gt;&lt;br /&gt;  &amp;lt;/exclusions&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;&lt;p&gt;How intuitive is that???&lt;/p&gt;&lt;p&gt;Maven should really do better, either by indicating the original coordinates when showing the dependency tree/list, or better yet by issuing a warning when trying to exclude a relocated dependency. I guess the latter one is not easy to implement, but current solution is just annoying!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-4419370443599774526?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/4419370443599774526/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/06/maven-how-relocated-artifacts-can-ruin.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4419370443599774526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4419370443599774526'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/06/maven-how-relocated-artifacts-can-ruin.html' title='Maven: How Relocated Artifacts Can Ruin Your Day'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-6313285457098238207</id><published>2009-06-17T16:33:00.008+02:00</published><updated>2009-09-08T09:23:43.437+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='Checkstyle'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Checkstyle: One and Only Configuration File?</title><content type='html'>&lt;h4&gt;The Checkstyle Challenge&lt;/h4&gt;&lt;p&gt;When you are using both Eclipse and Maven, you are probably facing the same challenge like we do: you would like to have a single configuration file for Checkstyle tool and reference that in Eclipse as well as in Maven. &lt;/p&gt;&lt;p&gt;&lt;a href="http://checkstyle.sourceforge.net/"&gt;Checkstyle&lt;/a&gt; ships with some default conventions (according to the Sun coding standards). But you usually want to customize this and create your own configuration set, based on your corporate coding styles. &lt;/p&gt;&lt;p&gt;Now, you want to setup Checkstyle within Eclipse to provide direct feedback to developers. You want to setup Checkstyle with Maven to be able to have a coprehensive report built as part of your project site. And you want both to reference the same configuration file, to avoid having to maintain two of them. Naturally, right? &lt;/p&gt;&lt;p&gt;Well, unfortunately, it seems impossible to achieve... if you really found a way, let me know!&lt;/p&gt;&lt;p&gt;However, there nonetheless are some tips to help you having a centralized configuration of Checkstyle with both tools. This post is about how to do that.&lt;/p&gt;&lt;h4&gt;Checkstyle with Maven&lt;/h4&gt;&lt;p&gt;The goal is to centralize the Checkstyle configuration to make its usage as simple as possible for all the projects, avoiding manual configuration as far as possible. Fortunately, this is quite easy using Maven's dependency mechanism.&lt;/p&gt;&lt;p&gt;Essentially, we build a custom artifact that contains nothing but our Checkstyle configuration file. This JAR is deployed to the company's Maven repository from where it can be downloaded as a normal dependency when needed. After that, the Checkstyle plugin is configured (in the &lt;em&gt;reporting&lt;/em&gt; section) to reference the packaged configuration file. That's it! &lt;/p&gt;&lt;p&gt;Now, we'll look at the details...&lt;/p&gt;&lt;p&gt;Let's assume our checkstyle configuration is located in &lt;code&gt;config/my-checkstyle.xml&lt;/code&gt;. Then the POM of the checkstyle artifact, which actually is a minimal Maven project, looks like this:&lt;/p&gt;&lt;pre class="brush:xml"&gt;  ...&lt;br /&gt;  &amp;lt;groupId&amp;gt;com.fja.ipl&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;checkstyle-config&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;build&amp;gt;&lt;br /&gt;    &amp;lt;resources&amp;gt;&lt;br /&gt;      &amp;lt;resource&amp;gt;&lt;br /&gt;        &amp;lt;directory&amp;gt;config&amp;lt;/directory&amp;gt;&lt;br /&gt;      &amp;lt;/resource&amp;gt;&lt;br /&gt;    &amp;lt;/resources&amp;gt;&lt;br /&gt;  &amp;lt;/build&amp;gt;&lt;br /&gt;  ...&lt;/pre&gt;&lt;p&gt;(Of course, you additionally have to add the &lt;em&gt;distributionManagement&lt;/em&gt; &lt;distributionmanagement&gt;section to be able to deploy the artifact, but this is usually derived by the company's base POM.) &lt;/p&gt;&lt;p&gt;Deploy the artifact. You'll notice that the created &lt;code&gt;checkstyle-config-1.0.jar&lt;/code&gt; indeed contains your &lt;code&gt;my-checkstyle.xml&lt;/code&gt; file in its root.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Now let's switch to the project that should use the Checkstyle report. The configuration file is referenced in the Checkstyle plug-in configuration in the &lt;em&gt;reporting&lt;/em&gt; section like this:&lt;/p&gt;&lt;pre class="brush:xml"&gt;  &amp;lt;reporting&amp;gt;&lt;br /&gt;    &amp;lt;plugins&amp;gt;&lt;br /&gt;      &amp;lt;plugin&amp;gt;&lt;br /&gt;        &amp;lt;artifactId&amp;gt;maven-checkstyle-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        &amp;lt;version&amp;gt;2.2&amp;lt;/version&amp;gt;&lt;br /&gt;        &amp;lt;configuration&amp;gt;&lt;br /&gt;          &amp;lt;configLocation&amp;gt;my-checkstyle.xml&amp;lt;/configLocation&amp;gt;&lt;br /&gt;        &amp;lt;/configuration&amp;gt;&lt;br /&gt;      &amp;lt;/plugin&amp;gt;&lt;br /&gt;      ...&lt;br /&gt;    &amp;lt;/plugins&amp;gt;&lt;br /&gt;  &amp;lt;/reporting&amp;gt;&lt;/pre&gt;&lt;p&gt;That is not yet working, Maven can't find this file – our &lt;code&gt;checkstyle-config&lt;/code&gt; artifact has not been referenced. We do this now by adding it as an &lt;a href="http://maven.apache.org/pom.html#Extensions"&gt;extension dependency&lt;/a&gt; to the POM as follows: &lt;/p&gt;&lt;pre class="brush:xml"&gt;  &amp;lt;build&amp;gt;&lt;br /&gt;    &amp;lt;extensions&amp;gt;&lt;br /&gt;      &amp;lt;extension&amp;gt;&lt;br /&gt;        &amp;lt;groupId&amp;gt;com.fja.ipl&amp;lt;/groupId&amp;gt;&lt;br /&gt;        &amp;lt;artifactId&amp;gt;checkstyle-config&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;&lt;br /&gt;      &amp;lt;/extension&amp;gt;&lt;br /&gt;    &amp;lt;/extensions&amp;gt;&lt;br /&gt;    ...&lt;br /&gt;  &amp;lt;/build&amp;gt;&lt;/pre&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;The artifacts configured as extensions will be included in the running build's classpath. That means, &lt;code&gt;checkstyle-config-1.0.jar&lt;/code&gt; now is in the classpath of the Checkstyle plugin, and the file referenced by the &lt;em&gt;configLocation&lt;/em&gt; setting is located in the JAR and hence can be found.&lt;/p&gt;&lt;p&gt;Using this approach, the Checkstyle configuration can be maintained centrally, and projects can get new versions simply by updating the artifact's version in the extension section.&lt;/p&gt;&lt;p&gt;&lt;h4&gt;Checkstyle with Eclipse&lt;/h4&gt;&lt;p&gt;Unfortunately, I don't really see a way to use the same Checkstyle configuration, packaged into the Maven artifact, with Eclipse as well...&lt;/p&gt;&lt;p&gt;So you'll have to duplicate the configuration file. However, to keep the number of duplicates small, I recommend to put it on a central network drive within your company and use the &lt;em&gt;Remote Configuration&lt;/em&gt; option of the Checkstyle Eclispe plugin to reference the remote file. This does not prevent you from working offline because Eclipse downloads and caches this file.&lt;/p&gt;&lt;p&gt;In this scenario, changing the Checkstyle configuration is done centrally by just updating the remote file. This is a great advantage over using a configuration that is part of the project, because in the latter case you would have to upgrade every single project.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-6313285457098238207?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/6313285457098238207/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/06/checkstyle-one-and-only-configuration.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/6313285457098238207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/6313285457098238207'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/06/checkstyle-one-and-only-configuration.html' title='Checkstyle: One and Only Configuration File?'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-1217472272543116103</id><published>2009-06-04T10:18:00.006+02:00</published><updated>2009-06-04T13:02:33.049+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google'/><title type='text'>Google and the Crystal Ball</title><content type='html'>&lt;p&gt;Google brought us the Web Search. They brought us the Maps. They brought us their Mail, the News, the Images, the Videos... In other words, they revolutionized the web. They rule the web. You all know that.&lt;/p&gt;&lt;p&gt;They are so creative, cutting-edge and are always good for some surprise. Like this one: Google has announced the &lt;a href="http://wave.google.com/"&gt;Wave&lt;/a&gt; project a few days ago, which indeed might have the power to turn into the "next generation of e-mail". Wave is a web based service platform designed to merge e-mail, instant messaging, wiki, and social networking. Gosh, this sounds exciting, really! &lt;/p&gt;&lt;p&gt;Yeah, Google is collecting data, probably more than we can imagine. And they will continue to do so. (A new &lt;a href="http://knowprivacy.org/web_bugs.html"&gt;study of UC Berkeley&lt;/a&gt; just revealed that Google is the dominant player in the tracking market; typically, tracking is done using "web bugs" that are embedded in the web page‘s HTML code, and are designed to enable monitoring of who is reading the page.)&lt;/p&gt;&lt;p&gt;But... aside from all discussions how evil or risky Google's data acquisitiveness might be, it opens a new world for something called "collective intelligence": discovering metadata based on the search engine data.&lt;/p&gt;&lt;p&gt;What does this mean? Well, Google records search phrases which can later be compared across specific regions, categories and time frames. Using Google's &lt;a href="http://www.google.com/insights/search"&gt;Insight for Search&lt;/a&gt; service, you can "see what the world is searching for". Pretty nice. For instance, search for "google wave" and see how the &lt;a href="http://www.google.com/insights/search/#q=google%20wave&amp;amp;date=today%2012-m&amp;amp;cmpt=q"&gt;interest emerged end of May&lt;/a&gt;. Interestingly enough, there have already been a few searches in summer 2008!?!&lt;/p&gt;&lt;p&gt;Well, it even gets better. Google has found out that certain search terms used in their web search are good indicators of flu activity – when people have the flu, they search for symptoms, drugs etc. Google uses that to estimate flu activity on their &lt;a href="http://www.google.org/flutrends/"&gt;Flu Trends&lt;/a&gt; page, and this indicator turns out to be quite good.&lt;/p&gt;&lt;p&gt;So, what is next? Possibilities seem endless, and Google will certainly surprise us again. Since they have all the data, and the (near) future is certainly hidden in that data – how about some kind of digital, web based crystal ball? I told you, so don't be surprised if they make it... ;o)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-1217472272543116103?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/1217472272543116103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/06/google-and-crystal-ball.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1217472272543116103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1217472272543116103'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/06/google-and-crystal-ball.html' title='Google and the Crystal Ball'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-8089255114782408699</id><published>2009-06-03T12:22:00.004+02:00</published><updated>2009-06-03T12:33:59.249+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Eclipse Top Annoyances</title><content type='html'>&lt;p&gt;Eclipse is one of those love/hate things. I love it and hate it, both at the same time.&lt;/p&gt;&lt;h4&gt;The Love&lt;/h4&gt;&lt;p&gt;Firstly, it's the best Java IDE on the market, and we successfully use it for years now. In the meantime, there might be other IDEs with an even richer feature set, better integration, nicer UI etc. but we actually don't care very much. I love Eclipse just for what it did to the Java and Open Source community, and it definitely has been pushing the edge for a couple of years now.&lt;/p&gt;&lt;p&gt;BTW, of course I know Eclipse is more than just a Java IDE, but this is my personal short interpretation of "development platform comprised of extensible frameworks, tools and runtimes for building, deploying and managing software across the lifecycle".&lt;/p&gt;&lt;h4&gt;The Hate&lt;/h4&gt;&lt;p&gt;Well, having said all this... sometimes Eclipse really drives me crazy. There are a couple of annoyances, some of them rather small but insistent, others bothering us since quite a long time.&lt;/p&gt;&lt;p&gt;The strange thing is, all of my complaints are not related to the more sophisticated plugins like Mylyn, WTP, MDT and so forth. (Yes, we use them too, albeit in a sketchy way.) No, the issues annoying me most are shown by the Platform or JDT, and maybe that's why they are actually so annoying.&lt;/p&gt;&lt;h4&gt;The List&lt;/h4&gt;&lt;p&gt;Okay, here is my list for Eclipse 3.4 (Ganymede):&lt;/p&gt;&lt;h5&gt;6. Formatting&lt;/h5&gt;&lt;p&gt;We have setup the Eclipse Java code formatter to match the project requirements. There are plenty of options to adjust to your needs, but... sometimes the algorithm is just broken. Take this example:&lt;/p&gt;&lt;pre&gt;private Accumulator getSpecificAccumAndSetRuleDefaultValue(&lt;br /&gt;                                                            CoverageRule calcStepRule,&lt;br /&gt;                                                            CalculationStepInfo calculationStepInfo,&lt;br /&gt;                                                            ...)&lt;br /&gt;{&lt;br /&gt;   ...&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;What is this extra line break before the first method argument good for? Instead of aligning the method arguments horizontally, Eclipse messed it up vertically. You can find several other strange formattings where formatted code requires extra space, mainly in long method or class declarations. Here is another example of an extra line break:&lt;/p&gt;&lt;pre&gt;public class PersistenceService&amp;lt;R extends PersistentRootObject, D extends HibernateDaoSupport&amp;gt;&lt;br /&gt;      implements&lt;br /&gt;         IPersistenceService&lt;r&gt; {&lt;br /&gt;  ...&lt;br /&gt;}&lt;/pre&gt;&lt;h5&gt;5. Blocking Workspace&lt;/h5&gt;&lt;p&gt;I have &lt;a href="http://javamoods.blogspot.com/2009/04/eclipse-user-operation-is-waiting-and.html"&gt;blogged&lt;/a&gt; about this blocking behaviour before: sometimes, Eclipse can't save my file while it is building "in the background" and tells me that my "User Operation is Waiting"...&lt;/p&gt;&lt;p&gt;That's just silly, Eclipse should be able to do my save action at any time, if compiling or not. Loosing editor's content (by unintended editing, Eclipse crash or hang-up, whatever) just due to the impossibility to save is just not acceptable.&lt;/p&gt;&lt;h5&gt;4. Startup Time&lt;/h5&gt;&lt;p&gt;Depending on size of the workspace, you got to wait minutes before you can start editing. That's just too slow. Period.&lt;/p&gt;&lt;h5&gt;3. Dialog Window Dimensions&lt;/h5&gt;&lt;p&gt;When you open a project's Properties window, for instance, it will show up quite small. I have a large screen and don't like to scroll unnecessarily, so I resize the window to be considerably larger. However, the dialog dimensions are not persisted – when I close and reopen the same dialog, it shows up as small as before. Eclipse just refuses to remember what I like.&lt;/p&gt;&lt;p&gt;For other dialog windows (like Open Type), this works perfectly; why not for all of them?&lt;/p&gt;&lt;h5&gt;2. Update Manager&lt;/h5&gt;&lt;p&gt;I used to think the new Eclipse 3.4 update manager (p2 Provisioning System) was a good thing, but I'm no longer sure. As end user, you just don't want to mess around with features, dependencies, build numbers... and get strange error messages (see &lt;a href="http://javamoods.blogspot.com/2009/05/eclipse-update-manager-fools-me.html"&gt;this post&lt;/a&gt; of an issue with a custom built Eclipse plugin we struggled with recently).&lt;/p&gt;&lt;p&gt;Additionally, the list of available software is too technical for most end users. Subversive SVN Connectors plugin provides 6 optional connectors, but at least one is required. So, which one(s) do I choose? Instead of having the full list with just the name and version strings, I would rather like to see some typical sets of required features ("typical installation" similary to when installing software on Windows). Alternatively, at least provide some end user level meta information like "This is the default feature", "Choose this item if..." etc. &lt;/p&gt;&lt;h5&gt;1. Vanished Project Contents&lt;/h5&gt;&lt;p&gt;Sometimes the content of my workspace projects in Package Explorer view is "gone", meaning I can't expand the project nodes any more. Yes, of course there &lt;em&gt;is&lt;/em&gt; some content, and fortunately it is still on the disk – but just not showing up in the view.&lt;/p&gt;&lt;p&gt;Project Explorer view still shows the projects correctly. Closing and re-opening them in Package Explorer usually helps. &lt;/p&gt;&lt;h4&gt;The Hope&lt;/h4&gt;&lt;p&gt;I used to install the latest milestones for some years, but have given up this habit because of stability/quality/compatibility issues with Eclipse core and/or the plugins I use. Hence, I can't tell which ones will be addressed by the Eclipse 3.5 (Galileo) which is going to happen on 24th of June.&lt;/p&gt;&lt;p&gt;So... let's keep our fingers crossed!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-8089255114782408699?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/8089255114782408699/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/06/eclipse-top-annoyances.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/8089255114782408699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/8089255114782408699'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/06/eclipse-top-annoyances.html' title='Eclipse Top Annoyances'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-691674893015969338</id><published>2009-05-18T13:47:00.004+02:00</published><updated>2009-05-18T13:50:23.044+02:00</updated><title type='text'>Maven Plugin Releases: Do it yourself!</title><content type='html'>&lt;p&gt;In my &lt;a href="http://javamoods.blogspot.com/2009/05/maven-compromised-by-plugins.html"&gt;previous post&lt;/a&gt;, I have complained about Maven plugins that do not release new versions although there are blocking issues that are reported in Jira with patches attached to them. If you don't want to wait any longer for a new plugin release, just build one on your own. Here's how we usually do that.&lt;/p&gt;&lt;h4&gt;Fix the Plugin&lt;/h4&gt;&lt;ol&gt;&lt;li&gt;Checkout plugin sources from source repository and import as Eclipse project. The easiest way to do this is to use m2eclipse plugin's cool "Materialize Maven Projects" feature (see &lt;a href="http://docs.codehaus.org/display/M2ECLIPSE/Importing+Maven+projects#ImportingMavenprojects-MaterializeMavenprojects"&gt;here&lt;/a&gt;).&lt;/li&gt;&lt;li&gt;Edit the POM and change the plugin's version number (see notes below). &lt;/li&gt;&lt;li&gt;Download the patch from the JIRA issue page.&lt;/li&gt;&lt;li&gt;Appy the patch using Eclipse: in project's context menu, select &lt;em&gt;Team &gt; Apply Patch...&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Now build, unit-test and install the plugin using Maven.&lt;/li&gt;&lt;li&gt;Update your project's POM to use this new version, and test, test, test.... &lt;/li&gt;&lt;li&gt;If everything is fine, upload your patched plugin to your repository manager to make it available to your team members.&lt;/li&gt;&lt;li&gt;Check in all changes you made, probably including the fixed plugin – into your repository, of course, not the plugin's one!&lt;/li&gt;&lt;/ol&gt;&lt;h4&gt;Give Some Thought to Version Numbers&lt;/h4&gt;&lt;p&gt;A few rules on the fixed plugin's version string that have proven rational for us:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;You should not just increase the version number&lt;/strong&gt; to prevent mix-up with future official versions of the plugin. &lt;/li&gt;&lt;li&gt;Instead, we usually &lt;strong&gt;add a suffix&lt;/strong&gt; made up of our company name and a consecutive number, like "-fja-1" for the first fix. This indicates the initiator and gives room for further fixes in case they should be required. Additionally, you always see the underlying official version. Example: &lt;code&gt;&amp;lt;version&amp;gt;2.5-fja-1&amp;lt;/version&amp;gt;&lt;/code&gt; for FJA's first fix of version 2.5.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Don't change the plugin's group or artifact id&lt;/strong&gt; because this would bypass Maven's version resolution, i.e. in Maven's eyes your fix would not just be a new version, but another plugin. You possibly end up having both plugins (the original one and your fix) configured in your builds, leading to duplicate execution and unexpected results.&lt;/li&gt;&lt;li&gt;If you just change the version string, this can be done in the parent POM – you are &lt;a href="http://www.sonatype.com/people/2008/04/maven-209-released/"&gt;locking down&lt;/a&gt; your plugins in your corporate/project root POM, do you? – making it easy to switch back to an official relase later... in case there is one available.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-691674893015969338?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/691674893015969338/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/05/maven-plugin-releases-do-it-yourself.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/691674893015969338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/691674893015969338'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/05/maven-plugin-releases-do-it-yourself.html' title='Maven Plugin Releases: Do it yourself!'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-5625674026192678603</id><published>2009-05-13T09:31:00.005+02:00</published><updated>2009-05-13T10:13:44.881+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Checkstyle'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven Compromised by Plugins</title><content type='html'>&lt;p&gt;Every piece of software has its flaws... The important part is how the project is dealing with bugs.&lt;/p&gt;&lt;h4&gt;Maven is fine&lt;/h4&gt;&lt;p&gt;With Maven, the situation actually is good enough: there have been releases of 2.0.x branch 1-2 times per year, to fix bugs and provide new features or improvements. At the same time, the 2.1.0 branch appeared with a milestone and a final release six month later. &lt;/p&gt;&lt;p&gt;However, you would usually not want to switch your Maven build system to a new version too often. This is always risky since a new version of the "core" may cause unexpected results in &lt;em&gt;any area&lt;/em&gt; of the build. A continuous integration engine helps to detect bugs, but you never know.&lt;/p&gt;&lt;p&gt;Fortunately, Maven is heavily based on plugins – which means if you encounter any issue with a specific Maven task, it's usually caused by the related plugin, not the Maven core. That's great, right? You just upgrade your POMs to use a new version of the particular plugin. Better isolation, fewer risks!&lt;/p&gt;&lt;h4&gt;(Some) Plugins are not!&lt;/h4&gt;&lt;p&gt;But... this assumes that there is a new version of the plugin available. Now imagine this: a plugin has a bug reported by the community, and there is a Jira issue for that. Some brave soul even attached a patch to fix the issue and others confirmed that it works for them. Thus, the new bugfix release could easily be built. But what happens? No new release. Nothing. Not even an alpha/beta version. Not even a comment explaining why. For months!&lt;/p&gt;&lt;p&gt;Here are just two examples we stumbled upon the last couple of weeks:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Javadoc plugin:&lt;/strong&gt; The report is not generated at all for multi-module project if run from parent level and using the recommended aggregate goal. &lt;a href="http://jira.codehaus.org/browse/MJAVADOC-181"&gt;Jira issue&lt;/a&gt; reported 2008/08/18, patch added 2008/09/22. No new release ever since.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;strong&gt;Checkstyle plugin:&lt;/strong&gt; Current version does not work with Checkstyle 5.0 that started to appear on the stage last summer. &lt;a href="http://jira.codehaus.org/browse/MCHECKSTYLE-105"&gt;Jira issue&lt;/a&gt; created 2008/10/28, along with a patch; another patch added 2009/03/27. No new release ever since. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Wow. How annoying is that? There is a major/blocking issue, and there is a patch available, but the plugin owners don't take the time or effort to create a new release?!? Why so? What else could the community do to help fixing the plugin?&lt;/p&gt;&lt;p&gt;This way, the plugins are compromising usability of Maven. IMHO, that's a serious issue...&lt;/p&gt;&lt;h4&gt;So, what can you do?&lt;/h4&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;If you don't want to continue waiting for a new plugin release, you have to build one on your own, for your "private use". That's quite easy, fortunately, and I'll probably post about that later. &lt;/p&gt;&lt;p&gt;However, this is actually not what a typical Maven user wants to do. The plugins should just do it right: release more often to fix their known bugs! You could increase the pressure a little bit by voting for the Jira issue or adding some comments, but my experiences are not too good ...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-5625674026192678603?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/5625674026192678603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/05/maven-compromised-by-plugins.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/5625674026192678603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/5625674026192678603'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/05/maven-compromised-by-plugins.html' title='Maven Compromised by Plugins'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-7738055405281854772</id><published>2009-05-11T16:12:00.003+02:00</published><updated>2009-05-11T16:20:06.439+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QA'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='Checkstyle'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Update to Checkstyle 5.0</title><content type='html'>&lt;h4&gt;Checkstyle 5 is available!&lt;/h4&gt;&lt;p&gt;This is good news: a new version of &lt;a href="http://checkstyle.sourceforge.net/index.html"&gt;Checkstyle&lt;/a&gt; is available that better supports Java 5 language features (like generics, annotations or package-info files). Additionally, some checks are cleaned up a bit, for instance concerning their parent in which they are contained. See the &lt;a href="http://checkstyle.sourceforge.net/releasenotes.html"&gt;release notes&lt;/a&gt; for details.&lt;/p&gt;&lt;p&gt;Due to these changes, Checkstyle 5.0 is not fully compatible to previous versions 4.x – which is already indicated by the version number leap. Hence, don't expect the upgrade to be smoothly!&lt;/p&gt;&lt;p&gt;Nevertheless, I thought it would be time to upgrade, so here is what I did...&lt;/p&gt;&lt;h4&gt;Step 1: Upgrade checkfile configuration&lt;/h4&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Due to the incompatabilities, I had to apply some changes to our checkstyle configuration to make it work with Checkstyle 5. To be sure I did it right, I have downloaded and used the Checkstyle binaries and checked my configuration for just a simple project. Hence, before upgrading Eclipse and Maven Checkstyle integration, I know my configuration is correct.&lt;/p&gt;&lt;p&gt;BTW, we are using a common checkstyle configuration file for all projects, and reference this "global" file with Maven and Eclipse in different ways: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;With Maven, we use a custom artifact that contains nothing but our checkstyle.xml file. This in turn is included as &lt;em&gt;build extension&lt;/em&gt; in our main base POM. See &lt;a href="http://www.gexperts.com/blog/archives/2007/05/entry_14.html"&gt;this post&lt;/a&gt; for more details.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;For Eclipse, we use the "Eclipse Checkstyle Plugin" that provides a &lt;em&gt;Remote Configuration&lt;/em&gt; option to reference the configuration file on an internal file server.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Step 2: Upgrade Eclipse Plugin&lt;/h4&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;There is a new Beta-Release of Eclipse Checkstyle plugin (eclipse-cs) available on its update site &lt;a href="http://eclipse-cs.sf.net/update"&gt;http://eclipse-cs.sf.net/update&lt;/a&gt;. At the time of writing, there are three features available:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Eclipse Checkstyle Plug-in – version 5.0.0-beta4&lt;/li&gt;&lt;li&gt;Eclipse Checkstyle Plug-in 4.4.x -&gt; 5.0.0 Migration (Optional) – version 5.0.0-beta4&lt;/li&gt;&lt;li&gt;m2eclipse Maven Synchronization Plugin (Optional/Experimental) – version 0.0.3&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Oh, seems there would have been some help in migrating from Checkstyle 4.4 to 5.0... Doesn't matter, I always like to see what the changes are so it's good to do it manually.&lt;/p&gt;&lt;p&gt;The m2eclipse Synchronization plugin is a &lt;a href="http://eclipse-cs.sourceforge.net/maven.html"&gt;new feature&lt;/a&gt; providing mechanism to synchronize Checkstyle rules and configuration between the maven plugin and eclipse-cs. Sounds really interesting... but let's do one step after the other and test this later.&lt;/p&gt;&lt;p&gt;So. I just installed the "Eclipse Checkstyle Plug-in" feature. Eclipse didn't recognize that this actually is an update, so you have to uninstall the previous eclipse-cs installation manually.&lt;/p&gt;&lt;p&gt;Why that? Well, the "package" has changed from &lt;code&gt;com.atlassw.tools.*&lt;/code&gt; to &lt;code&gt;net.sf.eclipsecs.*&lt;/code&gt;, and this applies to the feature's ID, too. Moreover, this renaming also affects the &lt;em&gt;buildCommand&lt;/em&gt; and &lt;em&gt;nature&lt;/em&gt; in &lt;code&gt;.project&lt;/code&gt; files, they have to be &lt;code&gt;net.sf.eclipsecs.core.CheckstyleBuilder&lt;/code&gt; and &lt;code&gt;&lt;br /&gt;net.sf.eclipsecs.core.CheckstyleNature&lt;/code&gt; now.&lt;/p&gt;&lt;p&gt;Additionally, the notation for file sets has been changed: a file set previously configured as &lt;code&gt;src\\main\\java\\com\\mycompany\\.*&lt;/code&gt; does no more match to any file; instead, it has to be the slash now like in &lt;code&gt;src/main/java/com/mycompany/.*&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Okay, maybe I should have tried the Migration plugin... Anyways, after these changes everything works fine for me in Eclipse.&lt;/p&gt;&lt;h4&gt;Step 3: Upgrade Maven Plugin&lt;/h4&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Good. Last piece is Maven, which provides the &lt;a href="http://maven.apache.org/plugins/maven-checkstyle-plugin/"&gt;Maven 2 Checkstyle Plugin&lt;/a&gt;. However, the current version is 2.2 which is based on Checkstyle 4.4 by defining these dependencies:&lt;/p&gt;&lt;pre&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;checkstyle&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;checkstyle&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;4.4&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;br /&gt;&amp;lt;dependency&amp;gt;&lt;br /&gt;  &amp;lt;groupId&amp;gt;checkstyle&amp;lt;/groupId&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;checkstyle-optional&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;4.4&amp;lt;/version&amp;gt;&lt;br /&gt;&amp;lt;/dependency&amp;gt;&lt;/pre&gt;There is an interesting way to &lt;a href="http://www.sonatype.com/people/2008/04/how-to-override-a-plugins-dependency-in-maven/"&gt;override the plugin's dependencies&lt;/a&gt; pointed out by Brian Fox, but that's &lt;a href="http://www.nabble.com/How-to-use-Checkstyle-5-td22102780.html"&gt;not going to work&lt;/a&gt; for us because Checkstyle versions 4.4 and 5.0 are not API compatible. &lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;What can we do? Not much... we'll have to wait for a new version of the Checkstyle plugin that updates to Checkstyle 5. There is this &lt;a href="http://jira.codehaus.org/browse/MCHECKSTYLE-105"&gt;Jira issue&lt;/a&gt;, and patches have already been provided some time ago. It's only that there seems to be no progress whatsoever... Checkstyle 5.0 is officially out since April 18th, so there is no reason to wait any longer! Create a new release (for my part, alpha/beta is fine as well) – &lt;strong&gt;please!!!&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;If you really need the plugin to be fixed now, you could checkout the plugin's sources and built your own version, applying the patch provided in the Jira issue. That works, but is nothing we want to do regularly!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-7738055405281854772?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/7738055405281854772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/05/update-to-checkstyle-50.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7738055405281854772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7738055405281854772'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/05/update-to-checkstyle-50.html' title='Update to Checkstyle 5.0'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-597471685761625683</id><published>2009-05-05T13:46:00.000+02:00</published><updated>2009-05-05T13:47:52.999+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Eclipse: Update Manager Fools Me</title><content type='html'>&lt;p&gt;Recently, we experienced an issue with a custom Eclipse plugin developed and hosted by my company. When trying to install the plugin into various versions of Eclipse Ganymede, the update manager always told me "Cannot find a solution satisfying the following requirements org.eclipse.ui [3.4.2.M20090204-0800]".&lt;/p&gt;&lt;p&gt;Finally, after some lost days of searching and trying, we discovered that this message is totally misleading: the issue was not caused by the feature org.eclipse.ui missing or being available only with wrong version. Instead, the reason was a misconfigured Manifest file of the custom plugin. It just defined wrong version for the required bundles (oAW, the MDA/MDD generator framework we use).&lt;/p&gt;&lt;p&gt;How nasty is that? Couldn't Eclipse update manager (p2) provide better support? More useful messages? Gosh!&lt;/p&gt;&lt;p&gt;Moreover, Eclipse update manager seems to cache the metadata of remote repositories. That might be nice to avoid network overhead of loading the repository again and again. But... when testing installation of different plugin versions with a local update site, it definitely gets into your way. The sad thing is, you can't get rid of the cached contents easily. You'd have to remove the site, restart Eclipse with &lt;code&gt;-clean&lt;/code&gt; option two times, and after that recreate the location. Could be made easier, really.&lt;/p&gt;&lt;p&gt;Eclipse update manager will once more be refactored in upcoming Eclipse 3.5 Galileo. Folks, don't mess it up again!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-597471685761625683?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/597471685761625683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/05/eclipse-update-manager-fools-me.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/597471685761625683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/597471685761625683'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/05/eclipse-update-manager-fools-me.html' title='Eclipse: Update Manager Fools Me'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-4049261481376765893</id><published>2009-05-04T12:11:00.002+02:00</published><updated>2009-05-07T13:05:23.260+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QA'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven Enforcer Plugin: cool and annoying</title><content type='html'>&lt;p&gt;As a Maven expert, you probably have heard of &lt;a href="http://maven.apache.org/plugins/maven-enforcer-plugin/"&gt;maven-enforcer-plugin&lt;/a&gt;, "The Loving Iron Fist of Maven", as they say.&lt;/p&gt;&lt;h4&gt;It's so cool!&lt;/h4&gt;&lt;p&gt;The idea is pretty cool: the plugin provides goals to ensure that the environment used to run Maven is like you – the POM author – expected it to be. There are checks for constraints on the version of Maven or JDK, on the OS family, to enforce certain dependency requirements, and much more. &lt;a href="http://maven.apache.org/enforcer/enforcer-rules/index.html"&gt;This list&lt;/a&gt; on the web site gives you an impression on what kind of checks are provided.&lt;/p&gt;&lt;p&gt;Do you know what happens when you write your POMs and settings for Maven version 2.0.9 or greater, but somebody is still using an outdated 2.0.4? Well, this kind of issues is annoying and you better make sure it does not happen. &lt;/p&gt;&lt;p&gt;The current version of maven-enforcer-plugin (at the time we set it up) was 1.0-alpha-4 which sounded not very mature, but nevertheless we decided to use it. For our projects, we identified a couple of things we wanted to check, and we configured the plugin accordingly:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Java Version: should be 1.5.&lt;/li&gt;&lt;li&gt;Maven version: must at least be 2.1.0.&lt;/li&gt;&lt;li&gt;Enforce defined versions for all plugins, and disallow any use of "LATEST", "RELEASE" or "SNAPSHOT" as a version for any plugin.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Hey, SNAPSHOT plugins are just dangerous and you should never, never ever depend on them. The only exclusion could be plugins developed inhouse, but actually, no – not really. Bah, don't use SNAPSHOT plugins. Period.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;So, we tried to setup our enforcer plugin configuration like this:&lt;/p&gt;&lt;pre&gt;&amp;lt;plugin&amp;gt;&lt;br /&gt;  &amp;lt;artifactId&amp;gt;maven-enforcer-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;  &amp;lt;version&amp;gt;1.0-alpha-4&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;executions&amp;gt;&lt;br /&gt;    &amp;lt;execution&amp;gt;&lt;br /&gt;      &amp;lt;id&amp;gt;enforce-versions&amp;lt;/id&amp;gt;&lt;br /&gt;      &amp;lt;goals&amp;gt;&lt;br /&gt;        &amp;lt;goal&amp;gt;enforce&amp;lt;/goal&amp;gt;&lt;br /&gt;      &amp;lt;/goals&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;        &amp;lt;rules&amp;gt;&lt;br /&gt;          &amp;lt;requireMavenVersion&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;[2.1.0,)&amp;lt;/version&amp;gt;&lt;br /&gt;          &amp;lt;/requireMavenVersion&amp;gt;&lt;br /&gt;          &amp;lt;requireJavaVersion&amp;gt;&lt;br /&gt;            &amp;lt;version&amp;gt;1.5&amp;lt;/version&amp;gt;&lt;br /&gt;          &amp;lt;/requireJavaVersion&amp;gt;&lt;br /&gt;          &amp;lt;requirePluginVersions&amp;gt;&lt;br /&gt;            &amp;lt;message&amp;gt;Best Practice is to always define plugin versions!&amp;lt;/message&amp;gt;&lt;br /&gt;            &amp;lt;banLatest&amp;gt;true&amp;lt;/banLatest&amp;gt;&lt;br /&gt;            &amp;lt;banRelease&amp;gt;true&amp;lt;/banRelease&amp;gt;&lt;br /&gt;            &amp;lt;banSnapshots&amp;gt;true&amp;lt;/banSnapshots&amp;gt;&lt;br /&gt;          &amp;lt;/requirePluginVersions&amp;gt;&lt;br /&gt;        &amp;lt;/rules&amp;gt;&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;    &amp;lt;/execution&amp;gt;&lt;br /&gt;  &amp;lt;/executions&amp;gt;&lt;br /&gt;&amp;lt;/plugin&amp;gt;&lt;/pre&gt;Of course, we wanted to apply the same checks on command line as within Eclipse when using m2eclipse plugin.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;It's so annoying!&lt;/h4&gt;&lt;p&gt;Well, and here is where the trouble started...&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shot one.&lt;/strong&gt; Oh, wait, we are using Maven version 2.1.0-M1 currently. Guess what? This is not included in range [2.1.0,) which means every version x &gt;= 2.1.0. Okay. Let's use [2.1.0-M1,) instead.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shot two.&lt;/strong&gt; What about Eclipse? The check fails within Eclipse, and it turns out that the version number reported by the Maven embedder used by m2eclipse (0.96 at that time) is 2.1-SNAPSHOT. Thus, enforcer fails and we'll have to use this for the Maven version specification:&lt;/p&gt;&lt;pre&gt;&amp;lt;version&amp;gt;[2.1.0-M1,),[2.1-SNAPSHOT,)&amp;lt;/version&amp;gt;&lt;/pre&gt;&lt;p&gt;Ugly, but still manageable...&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shot three.&lt;/strong&gt; My team reported the enforcer plugin to sometimes use some "thinking time" when checking the environment – it seems to hang for couple of seconds. We all see that betimes, and I have no idea what it is caused by. Actually, performing those version checks should be fast as light, right? &lt;/p&gt;&lt;p&gt;What makes this even worse is the fact that in multi-module builds, enforcer plugin is called for each subproject. It binds by default to the &lt;em&gt;validate&lt;/em&gt; lifecycle phase which is executed for every subproject. However, the environment does not change very much during a single build, so it would be sufficient to check that only once per Maven call...&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shot four.&lt;/strong&gt; When establishing the cool &lt;a href="http://sonar.codehaus.org/"&gt;Sonar&lt;/a&gt; quality management platform, Maven started to complain that "some plugins are missing valid versions". Seems that Sonar defines dependencies to other artifacts used internally, but doesn't give a version for them. All you can do is specify a version for those plugins in the &lt;code&gt;&amp;lt;pluginManagement&amp;gt;&lt;/code&gt; section of one of your parent POMs. That's actually not what you want: explicitely list versions for artifacts used internally by the current version of a build tool... But what else can you do? Completely disable the &lt;em&gt;requirePluginVersions&lt;/em&gt; check?&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Shot five.&lt;/strong&gt; After upgrading m2eclipse to version 0.97, it does not correctly handle our enforcer configuration any more and instead yields an error:&lt;/p&gt;&lt;pre&gt;org.apache.maven.lifecycle.LifecycleExecutionException: Invalid or missing parameters: [Mojo parameter [name: 'rules'; alias: 'null']] for mojo: org.apache.maven.plugins:maven-enforcer-plugin:1.0-alpha-4:enforce&lt;/pre&gt;&lt;p&gt;This is a &lt;a href="https://issues.sonatype.org/browse/MNGECLIPSE-1091"&gt;known issue&lt;/a&gt;, and you have to uncheck the "Skip Maven compiler plugin when processing resources" checkbox in the project's properties. That means, we have to change configuration for all our projects :-( &lt;/p&gt;&lt;p&gt;Moreover, it was the default to check this option and it seems to have negative performance impact when deselected.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Game over.&lt;/strong&gt; This is the point where we eliminated enforcer plugin. Too much pain for a little helper tool. One of those things that seems to be quite cool at first glance, but starts to annoy you very soon.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-4049261481376765893?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/4049261481376765893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/05/maven-enforcer-plugin-cool-and-annoying.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4049261481376765893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4049261481376765893'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/05/maven-enforcer-plugin-cool-and-annoying.html' title='Maven Enforcer Plugin: cool and annoying'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-2488466004288813103</id><published>2009-04-29T13:43:00.004+02:00</published><updated>2009-12-09T10:41:49.910+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven Documentation: The Missing List</title><content type='html'>&lt;p&gt;A rather weak talent of Maven is probably its documentation. This is my personal opinion, but it seem to match what &lt;a href="http://www.coderoshi.com/2007/09/maven-doesnt-suck-you-suck-and-maven.html"&gt;other&lt;/a&gt; &lt;a href="http://jbrugge.com/blog/2008/02/19/the-joy-and-sorrow-that-is-maven/"&gt;people&lt;/a&gt; &lt;a href="http://peterbacklund.blogspot.com/2009/03/five-tips-for-successfully-deploying.html"&gt;think&lt;/a&gt;. Yeah, it has been gotten better, but there is still some room...&lt;/p&gt;&lt;p&gt;It's not that there is not enough documentation available, it's just that the existing documentation is poorly organized and you often can't find what you need. Moreover, many documents (especially for plugins) are only scratching the surface, not even diving into the important shallows. Or, even worse, they give you wrong or inconsistent information...&lt;/p&gt;&lt;p&gt;Here is just one example: The surefire plugin page for surefire:test goal gives &lt;a href="http://maven.apache.org/plugins/maven-surefire-plugin/test-mojo.html#excludes"&gt;this description&lt;/a&gt; for the &lt;code&gt;excludes&lt;/code&gt; parameter: "List of patterns (separated by commas) used to specify the tests that should be excluded in testing. (...)". However, the example page for "Inclusions and Exclusions of Tests" &lt;a href="http://maven.apache.org/plugins/maven-surefire-plugin/examples/inclusion-exclusion.html"&gt;shows an example&lt;/a&gt; that uses nested &lt;code&gt;&lt;exclude&gt;&lt;/code&gt;elements – wait, what about the commas? So, what do you do? Go ahead and try yourself? I bet this type of annoyance is hitting every Maven newbie sooner or later.&lt;/p&gt;&lt;p&gt;Well, maybe the Maven team should start a &lt;strong&gt;coordinated, collaborative effort&lt;/strong&gt; to improve documentation just like Wikipedia is doing once in a while. Or, better yet, why not move all documentation into some &lt;strong&gt;open Wiki&lt;/strong&gt; and let the community work on what it thinks is missing, broken, inconsistent, badly organized, ...&lt;/p&gt;&lt;p&gt;Well, until then, we have to use what is available. This post tries to list most important pieces of online documentation, indispensable when you are dealing with Maven in a professional way. Let me know if you think something is missing on this list...&lt;/p&gt;&lt;h4&gt;Introductory &amp;amp; General&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://maven.apache.org/index.html"&gt;Main Site&lt;/a&gt; for Apache Maven project&lt;/li&gt;&lt;li&gt;&lt;a href="http://maven.apache.org/guides/getting-started/index.html"&gt;Maven Getting Started Guide&lt;/a&gt; – intended as a reference for those working with Maven for the first time&lt;/li&gt;&lt;li&gt;&lt;a href="http://docs.codehaus.org/display/MAVENUSER/The+Maven+2+tutorial"&gt;The Maven 2 tutorial&lt;/a&gt; – a practical guide for Maven 2 users from Codehaus&lt;/li&gt;&lt;li&gt;&lt;a href="http://maven.apache.org/general.html"&gt;offical FAQ&lt;/a&gt; and &lt;a href="http://docs.codehaus.org/display/MAVENUSER/FAQs-1"&gt;unofficial FAQ&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Sonatype's &lt;a href="http://www.sonatype.com/people/2009/04/summary-of-maven-how-tos/"&gt;Summary of Maven How-Tos&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.avajava.com/tutorials/categories/maven"&gt;List of Web Tutorials&lt;/a&gt; (How-To's)&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Books&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.sonatype.com/books/maven-book/reference/"&gt;Maven: The Definitive Guide&lt;/a&gt; – a free book by Sonatype (using a Creative Commons license). High quality, up-to-date, written by some of the famous Maven gurus: Tim O'Brien, John Casey, Brian Fox, Bruce Snyder and Jason Van Zyl.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.maestrodev.com/better-build-maven"&gt;Better Builds with Maven&lt;/a&gt; – another free book, originally maintained by Mergere, now managed by MaestroDev. This, too, is written by core members of the Apache Maven Project: Vincent Massol, Jason van Zyl, Brett Porter, et al.&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Technical Details&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;Maven plugins&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://maven.apache.org/plugins/index.html"&gt;Maven Plugins&lt;/a&gt; – lists the core plugins (supported by the Maven projects) and others &lt;/li&gt;&lt;li&gt;&lt;a href="http://mojo.codehaus.org/plugins.html"&gt;Mojo Project Plugins&lt;/a&gt; – hosted at Codehaus repository&lt;/li&gt;&lt;li&gt;&lt;a href="http://cargo.codehaus.org/Maven2+plugin"&gt;Cargo Maven Plugin&lt;/a&gt; – used to start/stop J2EE containers and deploy to them&lt;/li&gt;&lt;li&gt;&lt;a href="http://docbkx-tools.sourceforge.net/docbkx-maven-plugin/plugin-info.html"&gt;Docbkx Maven Plugin&lt;/a&gt; – hard to find, but useful for generating HTML/PDF from DocBook&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;The POM&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://maven.apache.org/pom.html"&gt;POM Reference&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://maven.apache.org/ref/current/maven-model/maven.html"&gt;Technical Project Descriptor&lt;/a&gt; and &lt;a href="http://maven.apache.org/maven-v4_0_0.xsd"&gt;POM Schema&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Other important references&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html"&gt;Directory Structure&lt;/a&gt; – description of the standard directory layout&lt;/li&gt;&lt;li&gt;&lt;a href="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html"&gt;Build Lifecycle&lt;/a&gt; – lifecycle basiscs and bindings&lt;/li&gt;&lt;li&gt;&lt;a href="http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide"&gt;Maven Properties&lt;/a&gt; – a list of properties available in Maven 2&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;h4&gt;Community&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://markmail.org/list/org.apache.maven.users"&gt;Maven User List&lt;/a&gt;, hosted at MarkMail&lt;/li&gt;&lt;li&gt;&lt;a href="http://markmail.org/list/org.apache.maven.dev"&gt;Maven Developer List&lt;/a&gt;, hosted at MarkMail&lt;/li&gt;&lt;li&gt;&lt;a href="http://jira.codehaus.org/browse/MNG"&gt;Maven Project Issue Tracking&lt;/a&gt; (Jira)&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Other Useful Links&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://repo1.maven.org/maven2/"&gt;Maven Central&lt;/a&gt; – official Maven 2 repository&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mavensearch.net/"&gt;MavenSearch.net&lt;/a&gt; – search several Maven repositories&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.jarvana.com/jarvana/"&gt;Jarvana search engine&lt;/a&gt; (Beta) – Maven-focused Java class and archive search engine&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mvnbrowser.com/pom-report.html"&gt;Maven POM Report&lt;/a&gt; – verify if the dependencies in your POM are up-to-date&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h4&gt;Updates&lt;/h4&gt;&lt;ul&gt;&lt;li&gt;2009/05/11: added link to Sonatype's "Summary of Maven How-Tos" blog post – definitely worth to be listed here...&lt;/li&gt;&lt;li&gt;2009/05/28: added link to Maven Properties Guide wiki page&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-2488466004288813103?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/2488466004288813103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/04/maven-documentation-missing-list.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2488466004288813103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2488466004288813103'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/04/maven-documentation-missing-list.html' title='Maven Documentation: The Missing List'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-4798790669430875046</id><published>2009-04-27T11:23:00.000+02:00</published><updated>2009-05-06T17:15:44.148+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QA'/><category scheme='http://www.blogger.com/atom/ns#' term='Spring'/><category scheme='http://www.blogger.com/atom/ns#' term='WebApp'/><title type='text'>Spring Web Flow: watch out!</title><content type='html'>&lt;p&gt;Starting in November 2008, we found a concurrency issue in our web applications that are based on the following framework stack:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Spring 2.5.4&lt;/li&gt;&lt;li&gt;Spring Web Flow 2.0.5&lt;/li&gt;&lt;li&gt;JSF 1.2_09&lt;/li&gt;&lt;li&gt;Facelets 1.1.14a&lt;/li&gt;&lt;li&gt;Trinidad 1.2.9&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;The issue&lt;/h4&gt;&lt;p&gt;For a single user, everything run fine. However, when multiple users hit the application, we got some strange exceptions occasionally – not always and not always at the same place. However, we managed to get this one regularly with our JMeter tests:&lt;/p&gt;&lt;pre&gt;SCHWERWIEGEND: Error Rendering View[/plan/FindPlan.xhtml]&lt;br /&gt;javax.el.PropertyNotFoundException: /file:/.../facelets/ipl-comboBox.xhtml @64,30 value="#{localField.jsfValue}": Target Unreachable, identifier 'localField' resolved to null&lt;br /&gt;at com.sun.facelets.el.TagValueExpression.getType(Tag ValueExpression.java:62)&lt;br /&gt;at org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.ValueRenderer.getDefaultConverter(ValueRend erer.java:78)&lt;br /&gt;at org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SimpleSelectOneRenderer.renderNonElementCon tent(SimpleSelectOneRenderer.java:323)&lt;br /&gt;at org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.FormElementRenderer.encodeAllAsNonElement(F ormElementRenderer.java:172)&lt;br /&gt;at org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.FormElementRenderer.encodeAll(FormElementRe nderer.java:105)&lt;br /&gt;at org.apache.myfaces.trinidad.render.CoreRenderer.delegateRenderer(CoreRenderer.java:335)&lt;br /&gt;....&lt;/pre&gt;&lt;p&gt;This exception got rendered on the page instead of the actual component. At other times, we got &lt;code&gt;java.lang.IllegalStateException&lt;/code&gt; and other funny behavior.&lt;/p&gt;&lt;p&gt;The strange thing is, the referenced variable is put into the flow scope, of course. Now that we took the time to debug into this issue, we can see that the scopes seem to be correctly filled and the property is actually there, it's just that the ELResolvers could not retrieve it... &lt;/p&gt;&lt;p&gt;Actually, we thought it would be caused by our Java or Spring configuration code, presumably using wrong bean scope or the like. &lt;/p&gt;&lt;h4&gt;...is fixed!&lt;/h4&gt;&lt;p&gt;Guess what... now I have been pointed to &lt;a href="http://jira.springframework.org/browse/SWF-976"&gt;this bug&lt;/a&gt; of Spring Web Flow version 2.0.5: Class &lt;code&gt;SimpleELContext&lt;/code&gt; is not thread-safe, but is stored in some application singletons :-( See &lt;a href="http://forum.springsource.org/showthread.php?p=238143"&gt;this&lt;/a&gt; or &lt;a href="http://forum.springsource.org/showthread.php?t=67359"&gt;this&lt;/a&gt; thread for more details.&lt;/p&gt;&lt;p&gt;The good news is, the bug is fixed in version 2.0.6; we have upgraded our projects and load tested them, and everything is just fine.&lt;/p&gt;&lt;h4&gt;But...&lt;/h4&gt;&lt;p&gt;IMO this is leaving a stale aftertaste. I'll tell you why.&lt;/p&gt;&lt;p&gt;That issue is a severe one: web applications using SWF 2.0.5 are just not working for concurrent users. Everybody using SWF in this version (maybe earlier versions as well) is affected. Given that, it seems strange that&lt;/p&gt;&lt;ul&gt;&lt;li&gt;the issue &lt;strong&gt;hasn't been reported and fixed earlier&lt;/strong&gt;: Version 2.0.5 has been published on 14th of November, and it took more than 2 weeks for the Jira issue to show up.&lt;/li&gt;&lt;li&gt;this issue is &lt;strong&gt;hard to find in the web&lt;/strong&gt;: Of course, we did some web research to find out if someone else might have a similar problem, but we did not find very much useful. The mentioned threads have started in February/March 2009 – did nobody suffer from this bug earlier than that? Why did nobody post this issue anywhere before?&lt;/li&gt;&lt;li&gt;the fact that this version is buggy &lt;strong&gt;hasn't been reported on Spring Source web pages&lt;/strong&gt;: Since it's rather threatening, why not put an eye-catcher message on the download page (or somewhere else) telling that this version is buggy and should not be used?&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I can see two reasons for this situation, and actually I don't like both: on one hand, there seems to be no load testing by Spring Web Flow team before doing a release; on the other hand, this version 2.0.5 is probably not used very much for real-world web applications by the community out there, and I honestly hope that this is not true to SWF as a whole...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-4798790669430875046?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/4798790669430875046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/04/spring-web-flow-watch-out.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4798790669430875046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4798790669430875046'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/04/spring-web-flow-watch-out.html' title='Spring Web Flow: watch out!'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-7710933779641049452</id><published>2009-04-24T09:18:00.000+02:00</published><updated>2009-04-24T10:10:31.348+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Eclipse: User Operation is Waiting, and Waiting, ...</title><content type='html'>&lt;p&gt;I am using Eclipse since quite a long time, sometimes around 2002. That was version 2.0, if I remember correctly. Since then, I have always upgraded to the latest version, if not milestone build. Most of the time I was quite happy with the stability and really appreciated all the evolving features and UI improvements.&lt;/p&gt;&lt;p&gt;One major improvement (it was in 3.0, right?) was when they moved builds to a background process, enabling you to continue working when the class or project needed to be compiled.&lt;/p&gt;&lt;p&gt;But... what is this? In all the latest release versions (3.4.0 ... 3.4.2) I sometimes get this dialog when trying to save a file:&lt;/p&gt;&lt;p&gt;&lt;a href="http://4.bp.blogspot.com/_ey2D_DPIY5E/SfFtl2MN5lI/AAAAAAAAACA/ISl2pEkPnXw/s1600-h/EclipseSaveIsWaiting.gif"&gt;&lt;img id="BLOGGER_PHOTO_ID_5328160331125352018" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 216px; TEXT-ALIGN: center" alt="" src="http://4.bp.blogspot.com/_ey2D_DPIY5E/SfFtl2MN5lI/AAAAAAAAACA/ISl2pEkPnXw/s400/EclipseSaveIsWaiting.gif" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Eclipse can't save my file while it is building "in the background"? Come on! Nota bene, I am not talking about .project files or other stuff the whole build could depend upon, it's also true for simple resources or even documentation files!&lt;/p&gt;&lt;p&gt;That's &lt;strong&gt;really&lt;/strong&gt; annoying. This is a &lt;strong&gt;modal dialog&lt;/strong&gt;, which means I have to wait &lt;strong&gt;for minutes&lt;/strong&gt; until build is complete or at least in a state where Eclipse thinks it can save the file. Of course, the user interface is blocked during that time... unless you cancel the save task.&lt;/p&gt;&lt;p&gt;I use the Eclipse Java EE package and additionally have installed a couple of regular plugins, like m2eclipse and oAW. So I can't tell for sure who is actually causing this mess, but on the other hand my installation is probably not so unusual and I'm sure others get this issue as well. There are some entries in various issue databases telling me that I'm right.&lt;/p&gt;&lt;p&gt;Eclipse is great and I (still) love it – but our relationship really gets poisoned by this kind of things... Maybe I try IntelliJ IDEA or NetBeans one day... I have warned you!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-7710933779641049452?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/7710933779641049452/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/04/eclipse-user-operation-is-waiting-and.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7710933779641049452'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7710933779641049452'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/04/eclipse-user-operation-is-waiting-and.html' title='Eclipse: User Operation is Waiting, and Waiting, ...'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfFtl2MN5lI/AAAAAAAAACA/ISl2pEkPnXw/s72-c/EclipseSaveIsWaiting.gif' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-1398183409508885727</id><published>2009-04-22T11:43:00.000+02:00</published><updated>2009-04-22T14:08:54.589+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Profiles'/><category scheme='http://www.blogger.com/atom/ns#' term='Nexus'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven Setting for Using a Single Repo Manager</title><content type='html'>In a previous &lt;a href="http://javamoods.blogspot.com/2009/03/maven-repositories-put-in-pom-or.html"&gt;post&lt;/a&gt; I have tried to explain why it's a good idea to define your Maven repository in your &lt;code&gt;settings.xml&lt;/code&gt; file instead of the POM.&lt;br /&gt;&lt;br /&gt;Of course, there is some information available on how to do this, for instance in the Maven &lt;a href="http://maven.apache.org/settings.html"&gt;Settings Reference&lt;/a&gt;, the &lt;a href="http://maven.apache.org/guides/mini/guide-mirror-settings.html"&gt;Mirrors Guide&lt;/a&gt;, or the great &lt;a href="http://www.sonatype.com/books/nexus-book/reference/maven-sect-single-group.html"&gt;Nexus book&lt;/a&gt; from Sonatype.&lt;br /&gt;&lt;br /&gt;Nevertheless, this setup of repositories, proxies and mirrors can be a bit tricky (and is quite confusing when just starting with Maven), so here is how we did that.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;How should it look like?&lt;/h4&gt;&lt;p&gt;We use the &lt;a href="http://nexus.sonatype.org/"&gt;Nexus&lt;/a&gt; repository manager and especially do like the repository groups which combine repositories into single logical repo. (This feature is also implemented by other products like Archiva or Artifactory, see this &lt;a href="http://docs.codehaus.org/display/MAVENUSER/Maven+Repository+Manager+Feature+Matrix"&gt;Feature Matrix&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Now, here is the approach we want to implement: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;Access the repository group "internal" for release and snapshot versions of all &lt;strong&gt;internal artifacts&lt;/strong&gt; that have been produced by our company&lt;/li&gt;&lt;li&gt;Use the "public" repository group to provide release versions of all &lt;strong&gt;external artifacts&lt;/strong&gt; (we don't want external snapshots!)&lt;/li&gt;&lt;li&gt;For downloading &lt;strong&gt;plugins&lt;/strong&gt;, use both the "public" as well as the "internal" repository group to get release versions (we don't want to use snaphot version of plugins!)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Don't use any other repository&lt;/strong&gt; than "public" or "internal", no matter what is configured in project's POM, inherited POM, transitive dependencies, dependencies of plugins, etc. -- never ever!&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Defining the Repositories&lt;/h4&gt;&lt;p&gt;This is the required repository definition: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;We use a profile (that is activated by default) to group the repositories. This is actually not required, but gives a bit more flexibility.&lt;/li&gt;&lt;li&gt;For artifact resolution, there are two repositories with id "central" and "internal" to provide public (external) respectively internal artifacts. &lt;/li&gt;&lt;li&gt;The definition for "central" repository is &lt;em&gt;overriding&lt;/em&gt; (by using the same id) the "central" repository already defined in the implicit super POM, which is using &lt;code&gt;repo1.maven.org&lt;/code&gt; for downloads.&lt;/li&gt;&lt;li&gt;The given URLs are only bogus and are overridden by mirror settings – see below. &lt;/li&gt;&lt;li&gt;Additionally, we define the same two repositories "central" and "internal" as plugin repositories (required by Maven to find plugins). However, in contrast to artifacts, snapshots are not allowed at all.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And here is how the code looks like:&lt;/p&gt;&lt;pre&gt;&amp;lt;profiles&amp;gt;&lt;br /&gt;  &amp;lt;profile&amp;gt;&lt;br /&gt;    &amp;lt;id&amp;gt;repo-config&amp;lt;/id&amp;gt;&lt;br /&gt;    &amp;lt;activation&amp;gt;&lt;br /&gt;      &amp;lt;activeByDefault&amp;gt;true&amp;lt;/activeByDefault&amp;gt;&lt;br /&gt;    &amp;lt;/activation&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;repositories&amp;gt;&lt;br /&gt;      &amp;lt;!-- repo "central": override Maven default,&lt;br /&gt;           mirrored to Nexus group "public" --&amp;gt;&lt;br /&gt;      &amp;lt;repository&amp;gt;&lt;br /&gt;        &amp;lt;id&amp;gt;central&amp;lt;/id&amp;gt;&lt;br /&gt;        &amp;lt;url&amp;gt;http://central&amp;lt;/url&amp;gt;&lt;br /&gt;        &amp;lt;releases&amp;gt;&lt;br /&gt;          &amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;          &amp;lt;updatePolicy&amp;gt;never&amp;lt;/updatePolicy&amp;gt;&lt;br /&gt;          &amp;lt;checksumPolicy&amp;gt;ignore&amp;lt;/checksumPolicy&amp;gt;&lt;br /&gt;        &amp;lt;/releases&amp;gt;&lt;br /&gt;        &amp;lt;snapshots&amp;gt;&lt;br /&gt;          &amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;&lt;br /&gt;        &amp;lt;/snapshots&amp;gt;&lt;br /&gt;      &amp;lt;/repository&amp;gt;&lt;br /&gt;      &amp;lt;!-- repo "internal": provides internal release and snapshot artifacts,&lt;br /&gt;           mirrored to Nexus group "internal" --&amp;gt;&lt;br /&gt;      &amp;lt;repository&amp;gt;&lt;br /&gt;        &amp;lt;id&amp;gt;internal&amp;lt;/id&amp;gt;&lt;br /&gt;        &amp;lt;url&amp;gt;http://internal&amp;lt;/url&amp;gt;&lt;br /&gt;        &amp;lt;releases&amp;gt;&lt;br /&gt;          &amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;          &amp;lt;updatePolicy&amp;gt;never&amp;lt;/updatePolicy&amp;gt;&lt;br /&gt;          &amp;lt;checksumPolicy&amp;gt;ignore&amp;lt;/checksumPolicy&amp;gt;&lt;br /&gt;        &amp;lt;/releases&amp;gt;&lt;br /&gt;        &amp;lt;snapshots&amp;gt;&lt;br /&gt;          &amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;          &amp;lt;updatePolicy&amp;gt;always&amp;lt;/updatePolicy&amp;gt;&lt;br /&gt;          &amp;lt;checksumPolicy&amp;gt;ignore&amp;lt;/checksumPolicy&amp;gt;&lt;br /&gt;        &amp;lt;/snapshots&amp;gt;&lt;br /&gt;      &amp;lt;/repository&amp;gt;&lt;br /&gt;    &amp;lt;/repositories&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;pluginRepositories&amp;gt;&lt;br /&gt;      &amp;lt;!-- plugin-repo "central": override Maven default,&lt;br /&gt;           mirrored to Nexus group "public" --&amp;gt;&lt;br /&gt;      &amp;lt;pluginRepository&amp;gt;&lt;br /&gt;        &amp;lt;id&amp;gt;central&amp;lt;/id&amp;gt;&lt;br /&gt;        &amp;lt;url&amp;gt;http://central&amp;lt;/url&amp;gt;&lt;br /&gt;        &amp;lt;releases&amp;gt;&lt;br /&gt;          &amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;          &amp;lt;updatePolicy&amp;gt;never&amp;lt;/updatePolicy&amp;gt;&lt;br /&gt;          &amp;lt;checksumPolicy&amp;gt;ignore&amp;lt;/checksumPolicy&amp;gt;&lt;br /&gt;        &amp;lt;/releases&amp;gt;&lt;br /&gt;        &amp;lt;snapshots&amp;gt;&lt;br /&gt;          &amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;&lt;br /&gt;        &amp;lt;/snapshots&amp;gt;&lt;br /&gt;      &amp;lt;/pluginRepository&amp;gt;&lt;br /&gt;      &amp;lt;!-- plugin-repo "internal": provides internal plugin releases,&lt;br /&gt;           mirrored to Nexus group "internal" --&amp;gt;&lt;br /&gt;      &amp;lt;pluginRepository&amp;gt;&lt;br /&gt;        &amp;lt;id&amp;gt;internal&amp;lt;/id&amp;gt;&lt;br /&gt;        &amp;lt;url&amp;gt;http://internal&amp;lt;/url&amp;gt;&lt;br /&gt;        &amp;lt;releases&amp;gt;&lt;br /&gt;          &amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;          &amp;lt;updatePolicy&amp;gt;never&amp;lt;/updatePolicy&amp;gt;&lt;br /&gt;          &amp;lt;checksumPolicy&amp;gt;ignore&amp;lt;/checksumPolicy&amp;gt;&lt;br /&gt;        &amp;lt;/releases&amp;gt;&lt;br /&gt;        &amp;lt;snapshots&amp;gt;&lt;br /&gt;          &amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;&lt;br /&gt;        &amp;lt;/snapshots&amp;gt;&lt;br /&gt;      &amp;lt;/pluginRepository&amp;gt;&lt;br /&gt;    &amp;lt;/pluginRepositories&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;/profile&amp;gt;&lt;br /&gt;&amp;lt;/profiles&amp;gt;&lt;/pre&gt;&lt;h4&gt;Defining the Mirrors&lt;/h4&gt;&lt;p&gt;After defining the repositories, two issues are left: we have to specify the correct URLs, and to make sure nobody uses any other repository. Both of this is done with the &lt;code&gt;&amp;lt;mirrors&amp;gt;&lt;/code&gt; definition.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Repository with id "internal" is mapped to the URL of the "internal" Nexus group; that is, Maven uses that URL instead of what is given with the repository definition (the bogus URL &lt;code&gt;http://internal&lt;/code&gt;). &lt;/li&gt;&lt;li&gt;Every other repository (specified by using &lt;code&gt;&amp;lt;mirrorOf&amp;gt;*&amp;lt;/mirrorOf&amp;gt;&lt;/code&gt;) is mapped to the URL of the "public" Nexus group.&lt;/li&gt;&lt;li&gt;This last definition not only maps the "central" repository to the correct URL, but also any other repository and hence ensures every request is locked down to the internal repository manager.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Again, here is the section from &lt;code&gt;settings.xml&lt;/code&gt; file:&lt;/p&gt;&lt;pre&gt;&amp;lt;mirrors&amp;gt;&lt;br /&gt;  &amp;lt;mirror&amp;gt;&lt;br /&gt;    &amp;lt;id&amp;gt;nexus-internal&amp;lt;/id&amp;gt;&lt;br /&gt;    &amp;lt;name&amp;gt;Nexus internal repository group&amp;lt;/name&amp;gt;&lt;br /&gt;    &amp;lt;url&amp;gt;http://our-nexus-server:8081/nexus/content/groups/internal&amp;lt;/url&amp;gt;&lt;br /&gt;    &amp;lt;mirrorOf&amp;gt;internal&amp;lt;/mirrorOf&amp;gt;&lt;br /&gt;  &amp;lt;/mirror&amp;gt;&lt;br /&gt;  &amp;lt;mirror&amp;gt;&lt;br /&gt;    &amp;lt;id&amp;gt;nexus-public&amp;lt;/id&amp;gt;&lt;br /&gt;    &amp;lt;name&amp;gt;Nexus public repository group&amp;lt;/name&amp;gt;&lt;br /&gt;    &amp;lt;url&amp;gt;http://our-nexus-server:8081/nexus/content/groups/public&amp;lt;/url&amp;gt;&lt;br /&gt;    &amp;lt;mirrorOf&amp;gt;*&amp;lt;/mirrorOf&amp;gt;&lt;br /&gt;  &amp;lt;/mirror&amp;gt;&lt;br /&gt;&amp;lt;/mirrors&amp;gt;&lt;/pre&gt;&lt;h4&gt;What about the Proxy?&lt;/h4&gt;&lt;p&gt;The &lt;code&gt;&amp;lt;proxy&amp;gt;&lt;/code&gt; section in the &lt;code&gt;settings.xml&lt;/code&gt; file can be used to define a network proxy that is used for some or all of your HTTP requests. In our configuration, since the Nexus repository manager is running on an internal server and Maven is configured to not connect to any other server, we just don't need this setting.&lt;/p&gt;&lt;p&gt;See &lt;a href="http://maven.apache.org/guides/mini/guide-proxies.html"&gt;Configuring a proxy&lt;/a&gt; for more details on Maven Proxies. BTW, it should now be very clear that &lt;em&gt;mirrors&lt;/em&gt; in the Maven world are something completely different than &lt;em&gt;proxies&lt;/em&gt;...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-1398183409508885727?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/1398183409508885727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/04/maven-setting-for-using-single-repo.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1398183409508885727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/1398183409508885727'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/04/maven-setting-for-using-single-repo.html' title='Maven Setting for Using a Single Repo Manager'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-2838077844974623960</id><published>2009-03-27T10:32:00.000+01:00</published><updated>2009-03-27T17:04:19.537+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nexus'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven Repositories: define in POM or settings?</title><content type='html'>If you are using Maven for more than just playing, you certainly have a repository Manager installed to both proxy artifacts downloaded from public repositories, and host your own artifacts to make them available to other team members and teams. (If you really really don't have one yet, consider using &lt;a href="http://nexus.sonatype.org/"&gt;Nexus&lt;/a&gt;, an open source Maven repository manager created by Sonatype.)&lt;br /&gt;&lt;br /&gt;Well, so you use a repository manager. Now, you need to tell Maven to use it to download all the missing artifacts. Moreover, as an organization, you usually want to control where the artifacts are downloaded from. This means you need to make sure that &lt;em&gt;all developers&lt;/em&gt; are using the identical set of repositories for &lt;em&gt;all the projects&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;There are two placed you could use to &lt;a href="http://maven.apache.org/guides/introduction/introduction-to-repositories.html"&gt;configure your repositories&lt;/a&gt;: in the project's POM, or in the &lt;code&gt;&amp;lt;settings&amp;gt;&lt;/code&gt; element on the &lt;code&gt;settings.xml&lt;/code&gt; file. This post will discuss both ways and tell you which one you should use ;-)&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The POM&lt;/h4&gt;&lt;br /&gt;The "innocent way" is to add a definition like this to your &lt;a href="http://maven.apache.org/pom.html#Repositories"&gt;POM&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;repositories&amp;gt;&lt;br /&gt;  &amp;lt;repository&amp;gt;&lt;br /&gt;    &amp;lt;id&amp;gt;internal&amp;lt;/id&amp;gt;&lt;br /&gt;    &amp;lt;name&amp;gt;Company internal repo&amp;lt;/name&amp;gt;&lt;br /&gt;    &amp;lt;url&amp;gt;http://your.company.org/nexus/content/groups/public&amp;lt;/url&amp;gt;&lt;br /&gt;    &amp;lt;releases&amp;gt;&lt;br /&gt;      &amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;      &amp;lt;updatePolicy&amp;gt;always&amp;lt;/updatePolicy&amp;gt;&lt;br /&gt;      &amp;lt;checksumPolicy&amp;gt;warn&amp;lt;/checksumPolicy&amp;gt;&lt;br /&gt;    &amp;lt;/releases&amp;gt;&lt;br /&gt;    &amp;lt;snapshots&amp;gt;&lt;br /&gt;      &amp;lt;enabled&amp;gt;false&amp;lt;/enabled&amp;gt;&lt;br /&gt;    &amp;lt;/snapshots&amp;gt;&lt;br /&gt;  &amp;lt;/repository&amp;gt;&lt;br /&gt;&amp;lt;/repositories&amp;gt;&lt;/pre&gt;Maven uses all declared repositories to find missing artifacts. If it can't find what it's looking for, Maven will also fall back to the repository &lt;em&gt;central&lt;/em&gt; which is defined in the built-in parent POM. However, this is usually not what you want; instead, all artifacts should be proxied by your repository manager.&lt;br /&gt;&lt;br /&gt;This can be prevented by "overloading" the central repository with your own repository manager, i.e. you just add a definition with &lt;code&gt;&amp;lt;id&amp;gt;central&amp;lt;/id&amp;gt;&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;When using a central repository manager, the definition of repositories should be the same for all your projects. This is usually done by putting this stuff to a company's base POM. But... if someone is starting in a clean environment, Maven will have to know where the repository is to find the project's parent POM, where it will find where the repository is... you're stuck.&lt;br /&gt;&lt;br /&gt;Moreover, any POM that is included by transitive dependencies may specifiy additional repositories which are not redirected like the &lt;em&gt;central&lt;/em&gt; repo. These external repositories are used by Maven to find all dependencies, even your internal ones that for sure are not hosted there; and you still do not really control where the artifacts are coming from.&lt;br /&gt;&lt;br /&gt;Hence, using POM to define your repositories does not really solve any problem. Just don't do that!&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The Settings&lt;/h4&gt;&lt;br /&gt;So, we end up with the alternative and &lt;strong&gt;recommended way&lt;/strong&gt; of defining your repositories: the &lt;a href="http://maven.apache.org/settings.html"&gt;settings&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;To really make sure that all developers and all projects are using the identical set of repositories, you should use &lt;a href="http://maven.apache.org/guides/mini/guide-mirror-settings.html"&gt;mirrors&lt;/a&gt; to tell Maven to redirect all artifact requests to your internal repository manager.&lt;br /&gt;&lt;br /&gt;Both the mirror and repository settings can be defined in the &lt;code&gt;settings.xml&lt;/code&gt; file. I think I will do another post to explain what a good setup would look like...&lt;br /&gt;&lt;br /&gt;There are two locations for &lt;code&gt;settings.xml&lt;/code&gt; file: &lt;/p&gt;&lt;ol&gt;&lt;li&gt;the Maven installation at &lt;code&gt;$M2_HOME/conf/settings.xml&lt;/code&gt;&lt;/li&gt;&lt;li&gt;the user's local settings: &lt;code&gt;${user.home}/.m2/settings.xml&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;Both can contain the same set of definitions. So, which one to use?&lt;br /&gt;&lt;br /&gt;Actually, both locations require the Maven user (your team members) to manually do some configuration in their setting file. This is general not preferred for the known reasons: everybody needs to do this manually, no automatic update if settings change later on, unexpected behaviour when someone forgets to adopt his/her file etc.&lt;br /&gt;&lt;br /&gt;The only way to avoid these drawbacks is to avoid all manual editing work, i.e. provide a central version of the settings file that is checked in to your sourcecode management system (SCM). This can't be done for the second option (user's settings) but it can be done for the first (installation settings) – if you &lt;strong&gt;put Maven installation under source control&lt;/strong&gt;.&lt;br /&gt;&lt;br /&gt;This sounds a bit strange at first (after all, it's an executable!) but is really clever IMO, for the following reasons:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;You make sure everybody uses the same version of Maven; no more Maven version dependencies!&lt;/li&gt;&lt;li&gt;You can use a relative path from your projects to the Maven installation if they are part of the same source repository, for instance in batch files, Eclipse launch configurations etc.&lt;/li&gt;&lt;li&gt;The correct settings are applied automatically and may be updated in the repository without requiring any editing by the developers (except for updating).&lt;/li&gt;&lt;li&gt;Maven installation is only around 2 MB of size, which is not really an issue for any SCM.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;The Bottom Line&lt;/h4&gt;&lt;br /&gt;To summarize, by &lt;strong&gt;putting your Maven installation in your SCM&lt;/strong&gt; as part of your project environment, and &lt;strong&gt;using central settings to configure Maven&lt;/strong&gt; to use your repository manager, you reduce dependency to local environment. And stabilizing your builds is always a good thing!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-2838077844974623960?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/2838077844974623960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/03/maven-repositories-put-in-pom-or.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2838077844974623960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2838077844974623960'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/03/maven-repositories-put-in-pom-or.html' title='Maven Repositories: define in POM or settings?'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-4711713817868323178</id><published>2009-03-25T00:41:00.001+01:00</published><updated>2009-09-08T09:20:12.302+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Performance'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimization'/><title type='text'>How big is BigDecimal?</title><content type='html'>Lately, there was a debate in our company about rounding of numbers, more specific on how, when and where to do that. &lt;br /&gt;&lt;br /&gt;One of the questions was if a calculation method should return a rounded value, or if the result should be precise and rounded by the caller. Another question was how to represent the values and which functionality to use to actually do the rounding.&lt;br /&gt;&lt;br /&gt;There was a suggestion to use &lt;code&gt;BigDecimal&lt;/code&gt; objects everywhere instead of simple &lt;code&gt;double&lt;/code&gt; types because this class provides convenient methods for doing rounding. &lt;br /&gt;&lt;br /&gt;Of course, when you need the higher precision, this might be a great choice. However, when you don't need that and are just using the class for being able to easily use it's rounding capabilities, the solution is probably over-engineered. Well, I voted against that mainly for two reasons: performance and object size.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;1) Performance&lt;/h4&gt;&lt;br /&gt;It's obvious that calculations with primitive data types are faster than with &lt;code&gt;BigDecimal&lt;/code&gt;s (or &lt;code&gt;BigInteger&lt;/code&gt;). But... how much?&lt;br /&gt;&lt;br /&gt;A small Java code snippet helps to estimate the performance penalty:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;final long iterations = 1000000;&lt;br /&gt;long t = System.currentTimeMillis();&lt;br /&gt;double d = 123.456;&lt;br /&gt;for (int i = 0; i &lt; iterations; i++) {&lt;br /&gt;    final double b = d * (&lt;br /&gt;                       (double)System.currentTimeMillis() &lt;br /&gt;                     + (double)System.currentTimeMillis());&lt;br /&gt;}&lt;br /&gt;System.out.println("double: "+(System.currentTimeMillis() - t));&lt;br /&gt;&lt;br /&gt;t = System.currentTimeMillis();&lt;br /&gt;BigDecimal bd = new BigDecimal("123.456");&lt;br /&gt;for (int i = 0; i &lt; iterations; i++) {&lt;br /&gt;    final BigDecimal b = bd.multiply(&lt;br /&gt;      BigDecimal.valueOf(System.currentTimeMillis()).add(&lt;br /&gt;      BigDecimal.valueOf(System.currentTimeMillis())));&lt;br /&gt;}&lt;br /&gt;System.out.println("java.math.BigDecimal: "+(System.currentTimeMillis() - t));&lt;/pre&gt;&lt;br /&gt;We are not interested in absolute numbers here, but only in the comparison between &lt;code&gt;double&lt;/code&gt;'s and &lt;code&gt;BigDecimal&lt;/code&gt;'s. It turns out that one million operations (each is one multiplication and one addition of a double value) takes approximately 3-4 times longer with &lt;code&gt;BigDecimal&lt;/code&gt; than with &lt;code&gt;double&lt;/code&gt;s (on my poor old laptop with Java 5).&lt;br /&gt;&lt;br /&gt;Interestingly, when trying the same for &lt;code&gt;BigInteger&lt;/code&gt; and &lt;code&gt;long&lt;/code&gt;, the factor is approximately 5, i.e. the performance difference is even higher.&lt;br /&gt;&lt;br /&gt;With Java 6, the method runs faster for all types, but calculation with primitives has a greater improvement so that the performance penalty for using &lt;code&gt;Big*&lt;/code&gt; is even higher: 4-5 for &lt;code&gt;BigDecimal&lt;/code&gt;, 6 for &lt;code&gt;BigInteger&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;2) Object Size&lt;/h4&gt;&lt;br /&gt;Everybody would expect that a &lt;code&gt;BigDecimal&lt;/code&gt; would need more memory than a primitive &lt;code&gt;double&lt;/code&gt;, right? But, how much is it? We are going to have big objects with up to hundreds of decimal values, so the bigger &lt;code&gt;BigDecimal&lt;/code&gt;'s might sum up to a critical value when thinking of transporting those objects between processes (web service calls) or holding them in the session (for web applications).&lt;br /&gt;&lt;br /&gt;It happended that I have blogged about how to determine an object's size in my &lt;a href="http://javamoods.blogspot.com/2009/03/size-of-java-objects.html"&gt;last post&lt;/a&gt; ;-)  Hence, we can just move on to the actual figures:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;double&lt;/code&gt;: 8 bytes&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;Double&lt;/code&gt;: 16 bytes (8 bytes overhead for the class, 8 bytes for the contained &lt;code&gt;double&lt;/code&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;BigDecimal&lt;/code&gt;: 32 bytes&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;long&lt;/code&gt;: 8 bytes&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;Long&lt;/code&gt;: 16 bytes (8 bytes overhead for the class, 8 bytes for the contained &lt;code&gt;long&lt;/code&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;BigInteger&lt;/code&gt;: 56 bytes&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Wow. It seems that &lt;code&gt;BigDecimal&lt;/code&gt; is 4 times as big than  &lt;code&gt;double&lt;/code&gt; and twice the size of &lt;code&gt;Double&lt;/code&gt; &amp;ndash; which is not that bad. As before, &lt;code&gt;BigInteger&lt;/code&gt; has a bigger penalty with respect to object size as well.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;3) Conclusion&lt;/h4&gt;&lt;br /&gt;All in all, when using &lt;code&gt;BigDecimal&lt;/code&gt; instead of &lt;code&gt;double&lt;/code&gt;, this means factor 4 for both memory footprint as well as performance penalty. A good reason to not use &lt;code&gt;BigDecimal&lt;/code&gt;'s just for using the rounding functionality...!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-4711713817868323178?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/4711713817868323178/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/03/how-big-is-bigdecimal.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4711713817868323178'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4711713817868323178'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/03/how-big-is-bigdecimal.html' title='How big is BigDecimal?'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-4859981716342331025</id><published>2009-03-23T10:13:00.000+01:00</published><updated>2009-03-24T16:33:14.760+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Size'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Optimization'/><title type='text'>Size of Java Objects</title><content type='html'>I'm sure you know that measuring the size of objects in Java is not so easy since there is no C style &lt;code&gt;sizeof()&lt;/code&gt; functionality. Additionally, the actual size used to store an object on the Java heap depends on several variables: the JVM implementation, operation system (32/64 Bit) etc. Hence, a particular value for the amount of storage consumed by an object can be compared to the size of another object, but not between different runtime environments.&lt;br /&gt;&lt;br /&gt;So... how can the size of an object (i.e. it's memory usage) be determined? There are actually two possibilities. Both are well-known and not invented by me, so I only provide some basic information and links.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1) Use &lt;code&gt;Runtime.freeMemory()&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;The usual (old-fashioned) way to estimate the size of an object is like this: call garbage collector (GC) to ensure all unused memory is freed, then count current memory consumption (&lt;em&gt;M1&lt;/em&gt;), construct the object, GC once again and count memory (&lt;em&gt;M2&lt;/em&gt;). The difference &lt;em&gt;M2-M1&lt;/em&gt; indicates the amount of memory used for the created object.&lt;br /&gt;&lt;br /&gt;There are a few things to note:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;A single call to GC is more or less only a suggestion to the Java Virtual Machine to reclaim space from all discarded objects &amp;ndash; it's no guarantee that GC has been finished (method is not blocking) and all old objects have been removed. To be a bit more aggressive, GC should be used a couple of times.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;To make sure that supplementary memory (for static data etc.) is already allocated before starting memory count, you should construct an object and set the handle to null before starting the estimation cycle described above.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The precision might increase when creating not a single object, but a large amount of them.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;JavaWorld's &lt;a href="http://www.javaworld.com/javaworld/javatips/jw-javatip130.html"&gt;Java Tip 130&lt;/a&gt; described this approach, and Heinz Kabutz published two JavaSpecialists newsletters (Issue &lt;a href="http://www.javaspecialists.eu/archive/Issue029.html"&gt;29&lt;/a&gt;, &lt;a href="http://www.javaspecialists.eu/archive/Issue078.html"&gt;78&lt;/a&gt;) about determining memory usage in Java. &lt;br /&gt;&lt;br /&gt;Addtionally, there is an open source project &lt;a href="http://sourceforge.net/projects/sizeof"&gt;java.sizeOf&lt;/a&gt; at SourceForge using this approach.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2) Use &lt;code&gt;Instrumentation.getObjectSize()&lt;/code&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Starting with Java 5 there is a new method to determine object size: the &lt;a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/Instrumentation.html"&gt;instrumentation interface&lt;/a&gt;. It's &lt;code&gt;getObjectSize()&lt;/code&gt; method is still an estimate, but seems to provide more accurate results, albeit a bit slower than counting free memory. &lt;br /&gt;&lt;br /&gt;In short, you have to implement an instrumentation agent that contains a &lt;code&gt;premain(String, Instrumentation)&lt;/code&gt; method that will be called by the JVM on startup. The given instrumentation can be used to call methods on it later on. The agent has to be packaged into a JAR file that requires a &lt;code&gt;Premain-Class&lt;/code&gt; specification in it's manifest file. To use the instrumentation agent, call java with the &lt;code&gt;-javaagent&lt;/code&gt; option. For more information, see &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/instrument/package-summary.html"&gt;here&lt;/a&gt; and &lt;a href="http://javahowto.blogspot.com/2006/07/javaagent-option.html"&gt;this&lt;/a&gt; blog post.&lt;br /&gt;&lt;br /&gt;Guess what, Heinz Kabutz has published another JavaSpecialists newsletter &lt;a href="http://www.javaspecialists.eu/archive/Issue142.html"&gt;142&lt;/a&gt; describing this approach (you see, it's really worth subscribing!). Refer to &lt;a href="http://today.java.net/pub/a/today/2008/04/24/add-logging-at-class-load-time-with-instrumentation.html"&gt;this java.net article&lt;/a&gt; for another example of how to use Java instrumentation.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;That's it for today... One more remark: note that both described ways are not able to provide exact figures, but only &lt;em&gt;estimates&lt;/em&gt; of memory consumption. This is not really an issue because these estimates are typically exact for small objects, and size of complex data structures can be calculated using the known size of basic types and data structures.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-4859981716342331025?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/4859981716342331025/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/03/size-of-java-objects.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4859981716342331025'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/4859981716342331025'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/03/size-of-java-objects.html' title='Size of Java Objects'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-7590658180199264970</id><published>2009-03-20T13:26:00.001+01:00</published><updated>2009-03-24T16:34:15.044+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='QA'/><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><title type='text'>Sonar is SO cool!</title><content type='html'>Do you know Maven? Then you know the project site that can be easily generated with Maven. For instance, look at the site for the &lt;a href="http://mojo.codehaus.org/tomcat-maven-plugin/"&gt;Tomcat Maven plugin&lt;/a&gt;. It provides information on using the plugin, project related information and &amp;ndash; probably most importantly for most "normal" (i.e. non-plugin) projects &amp;ndash; the project reports. &lt;br /&gt;&lt;br /&gt;You can easily configure Maven to execute a number of useful reports like JavaDoc, Checkstyle, PMD (coding rule verification), CPD (duplicate code detection), and JUnit test coverage. Additionally, you can install custom reports to also participate in project site.&lt;br /&gt;&lt;br /&gt;This is great, but still lacks some features: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;What if you would like to see overall code quality, without having to consult several detailed reports? Just a single, combined indicator?&lt;/li&gt;&lt;br /&gt;&lt;li&gt;With the reports, it's not always easy to drill down a particular issue up to source code level.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It would be nice to be able to access historic versions and compare quality between them to early recognize trends, wouldn't it?&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;All this (and more) is provided by Sonar (&lt;a href="http://sonar.codehaus.org/"&gt;http://sonar.codehaus.org/&lt;/a&gt;), an open source tool that "enables to collect, analyze and report metrics on source code. Sonar not only offers consolidated reporting on and across projects throughout time, but it becomes the central place to manage code quality."&lt;br /&gt;&lt;br /&gt;Sonar collects data provided by well-known Maven reports, stores them into a database, and provides a modern, fast and convenient user interface to browse the projects and quality metrics, and to drill down from project to Java code level.&lt;br /&gt;&lt;br /&gt;Just look at the screenshot of an internal test project... how cool is that?&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_ey2D_DPIY5E/ScORtp5t56I/AAAAAAAAAAM/PTKF3Wbka-U/s1600-h/sonar.gif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 192px;" src="http://1.bp.blogspot.com/_ey2D_DPIY5E/ScORtp5t56I/AAAAAAAAAAM/PTKF3Wbka-U/s320/sonar.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5315252198755395490" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Installation is as simple as it can be. You can use Sonar with provided Jetty or install it in your existing container. For production, you can switch from embedded Derby database to a "real" database (like MySQL, Oracle, SqlServer, ...). Of course, you can adjust the rules to be checked or import your existing configuration (for Checkstyle or PMD). &lt;br /&gt;&lt;br /&gt;To send data to Sonar, you just execute a Maven command to call a particular &lt;code&gt;sonar-maven-plugin&lt;/code&gt; for your project:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;mvn clean install org.codehaus.sonar:sonar-maven-plugin:1.6:sonar&lt;/pre&gt;&lt;br /&gt;That's it... now watch all the magic going on.&lt;br /&gt;&lt;br /&gt;This Maven goal can be called manually, but is best integrated with nightly builds. To further simplify this, there is a &lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Sonar+plugin"&gt;Sonar plugin&lt;/a&gt; for &lt;a href="https://hudson.dev.java.net/"&gt;Hudson&lt;/a&gt;, my favorite continuous integration engine. Using this nice plugin, configuration of a Job to connect to Sonar is as simple as clicking a checkbox in post-build section!&lt;br /&gt;&lt;br /&gt;Sonar is &lt;em&gt;so great&lt;/em&gt; I really wonder why I didn't find this tool earlier &amp;ndash; current version is 1.6, so it must have been out for a while... You definitely should give it a try!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-7590658180199264970?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/7590658180199264970/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/03/sonar-is-so-cool.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7590658180199264970'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/7590658180199264970'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/03/sonar-is-so-cool.html' title='Sonar is SO cool!'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ey2D_DPIY5E/ScORtp5t56I/AAAAAAAAAAM/PTKF3Wbka-U/s72-c/sonar.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6189016616585694043.post-2369531587489296773</id><published>2009-03-19T12:51:00.000+01:00</published><updated>2009-03-19T14:04:33.425+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Profiles'/><category scheme='http://www.blogger.com/atom/ns#' term='Maven'/><title type='text'>Maven Profiles: Activation... or not</title><content type='html'>I love Maven. Really, I do. I should say that since this is my first post in my own blog (I know, I'm probably the last man on the planet... ;o) Having said this, here is another annoyance. There are lots of them, inside and outside of Maven, and I'm going to share some of my experiences here.&lt;br /&gt;&lt;br /&gt;This time, it's about Profiles. I'm not going to explain the basics (see &lt;a href="http://maven.apache.org/guides/introduction/introduction-to-profiles.html"&gt;Introduction to Build Profiles&lt;/a&gt; or the &lt;a href="http://www.sonatype.com/books/maven-book/reference/profiles.html"&gt;chapter on profiles&lt;/a&gt; in Maven: The Definitive Guide, for instance).&lt;br /&gt;&lt;br /&gt;I wanted to use profiles to specify some re-usable configuration (for code generation out of oAW models, but that doesn't matter) in a parent POM, without having to repeat all the stuff in child POMs. The profile definition in &lt;strong&gt;parent POM&lt;/strong&gt; consists of a plugin configuration along with required dependencies and looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;profile&amp;gt;&lt;br /&gt;  &amp;lt;id&amp;gt;adsl&amp;lt;/id&amp;gt;&lt;br /&gt;  &amp;lt;build&amp;gt;&lt;br /&gt;    &amp;lt;plugins&amp;gt;&lt;br /&gt;      &amp;lt;plugin&amp;gt;&lt;br /&gt;        &amp;lt;groupId&amp;gt;org.fornax.toolsupport&amp;lt;/groupId&amp;gt;&lt;br /&gt;        &amp;lt;artifactId&amp;gt;fornax-oaw-m2-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;        ... all the execution and configuration details ...&lt;br /&gt;      &amp;lt;/plugin&amp;gt;      &lt;br /&gt;    &amp;lt;/plugins&amp;gt;&lt;br /&gt;  &amp;lt;/build&amp;gt;&lt;br /&gt;  &amp;lt;dependencies&amp;gt;&lt;br /&gt;    &amp;lt;dependency&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;com.fja.ipl.adsl&amp;lt;/groupId&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;adsl&amp;lt;/artifactId&amp;gt;&lt;br /&gt;      &amp;lt;version&amp;gt;${ipl.current.version}&amp;lt;/version&amp;gt;&lt;br /&gt;    &amp;lt;/dependency&amp;gt;&lt;br /&gt;    ... and some more ...&lt;br /&gt;  &amp;lt;/dependencies&amp;gt;&lt;br /&gt;&amp;lt;/profile&amp;gt;&lt;/pre&gt;&lt;br /&gt;Then I tried to activate the profile in those child POMs that should use it since they are based on an oAW model. Note that I wanted to activate the profile in the POM itself, not throug settingings or command line options. And this is where the pain begins...&lt;br /&gt;&lt;br /&gt;First attempt was to just activate the profile in a &lt;strong&gt;child POM&lt;/strong&gt; like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;profile&amp;gt;&lt;br /&gt;  &amp;lt;id&amp;gt;adsl&amp;lt;/id&amp;gt;&lt;br /&gt;  &amp;lt;activation&amp;gt;&lt;br /&gt;    &amp;lt;activeByDefault&amp;gt;true&amp;lt;/activeByDefault&amp;gt;&lt;br /&gt;  &amp;lt;/activation&amp;gt;&lt;br /&gt;&amp;lt;/profile&amp;gt;&lt;/pre&gt;&lt;br /&gt;However, instead of activating the inherited profile with the given id, Maven just &lt;em&gt;overrides&lt;/em&gt; the profile from parent POM with a new (and empty) one. Okay, this might be the desired behaviour.&lt;br /&gt;&lt;br /&gt;So, next attempt was to use the activation on a present file: whenever there is a workflow file &lt;code&gt;src/main/resources/generateAll.oaw&lt;/code&gt;, the profile should be active. This is obvious, since oAW generation uses this workflow file anyways. &lt;strong&gt;Parent POM&lt;/strong&gt; now looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;profile&amp;gt;&lt;br /&gt;  &amp;lt;id&amp;gt;adsl&amp;lt;/id&amp;gt;&lt;br /&gt;  &lt;strong&gt;&amp;lt;activation&amp;gt;&lt;br /&gt;    &amp;lt;file&amp;gt;&lt;br /&gt;      &amp;lt;exists&amp;gt;src/main/resources/generateAll.oaw&amp;lt;/exists&amp;gt;&lt;br /&gt;    &amp;lt;/file&amp;gt;&lt;br /&gt;  &amp;lt;/activation&amp;gt;&lt;/strong&gt;&lt;br /&gt;  ...&lt;br /&gt;&amp;lt;/profile&amp;gt;&lt;/pre&gt;&lt;br /&gt;This works great... almost. When dealing with multi-module projects, it depends on from where you start the Maven build. For instance, let's assume project P aggregates modules M1 and M2. When you step down to M1 and start Maven, the file can be found in context of M1 and the profile is activated, so everything is just fine. Same is true for M2. However, when the build is started for project P, the file is searched in P's context where it can be found and hence the build of M1 and M2 fails.&lt;br /&gt;&lt;br /&gt;Sounds not that complicated... let's just use the &lt;code&gt;${basedir}&lt;/code&gt; property:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;exists&amp;gt;&lt;strong&gt;${basedir}&lt;/strong&gt;/src/main/resources/generateAll.oaw&amp;lt;/exists&amp;gt;&lt;/pre&gt;&lt;br /&gt;Well, it appears that this property is not expanded at all (see &lt;a href="http://jira.codehaus.org/browse/MNG-1775"&gt;MNG-1775&lt;/a&gt;). Thus, this doesn't work either.&lt;br /&gt;&lt;br /&gt;So, we're stuck. I don't have any other idea (do you?)...&lt;br /&gt;&lt;br /&gt;This might not be the typical use case for profiles, which are meant to modify the POM at build time to support environment/platform specifics. Agreed. However, as long as there is no other way of defining complex configuration in parent POM that should be reused in some (not all) child POMs, this would have been a useful approach, IMHO.&lt;br /&gt;&lt;br /&gt;Now, we end up in defining the plugin configuration in &lt;code&gt;&amp;lt;pluginManagement&amp;gt;&lt;/code&gt; section and to enable it and add required dependencies in child POMs. That is, we have to repeat the following section in &lt;em&gt;every single child project&lt;/em&gt; that want to harness oAW generation:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;lt;build&amp;gt;&lt;br /&gt;  &amp;lt;plugins&amp;gt;&lt;br /&gt;    &amp;lt;plugin&amp;gt;&lt;br /&gt;      &amp;lt;groupId&amp;gt;org.fornax.toolsupport&amp;lt;/groupId&amp;gt;&lt;br /&gt;      &amp;lt;artifactId&amp;gt;fornax-oaw-m2-plugin&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;/plugin&amp;gt;&lt;br /&gt;  &amp;lt;/plugins&amp;gt;&lt;br /&gt;&amp;lt;/build&amp;gt;&lt;br /&gt;&amp;lt;dependencies&amp;gt;&lt;br /&gt;  &amp;lt;dependency&amp;gt;&lt;br /&gt;    &amp;lt;groupId&amp;gt;com.fja.ipl.adsl&amp;lt;/groupId&amp;gt;&lt;br /&gt;    &amp;lt;artifactId&amp;gt;adsl&amp;lt;/artifactId&amp;gt;&lt;br /&gt;    &amp;lt;version&amp;gt;${ipl.current.version}&amp;lt;/version&amp;gt;&lt;br /&gt;  &amp;lt;/dependency&amp;gt;&lt;br /&gt;  ... and more of them ...&lt;br /&gt;&amp;lt;/dependencies&amp;gt;&lt;/pre&gt;&lt;br /&gt;Cumbersome, redundant, hard to maintain. Maven should do better, really!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6189016616585694043-2369531587489296773?l=javamoods.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://javamoods.blogspot.com/feeds/2369531587489296773/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://javamoods.blogspot.com/2009/03/maven-profiles-activation-or-not.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2369531587489296773'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6189016616585694043/posts/default/2369531587489296773'/><link rel='alternate' type='text/html' href='http://javamoods.blogspot.com/2009/03/maven-profiles-activation-or-not.html' title='Maven Profiles: Activation... or not'/><author><name>::Christoph</name><uri>http://www.blogger.com/profile/13039853176384586281</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='24' height='32' src='http://4.bp.blogspot.com/_ey2D_DPIY5E/SfDcjgUT0xI/AAAAAAAAABY/9pabXajkCtQ/S220/chams.gif'/></author><thr:total>0</thr:total></entry></feed>
