<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="https://raibledesigns.com/roller-ui/styles/rss.xsl" media="screen"?><rss version="2.0" 
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:atom="http://www.w3.org/2005/Atom" >
<channel>
  <title>Raible Designs</title>
  <link>https://raibledesigns.com/rd/</link>
      <atom:link rel="self" type="application/rss+xml" href="https://raibledesigns.com/rd/feed/entries/rss?tags=maven" />
    <description>Raible Designs is an Enterprise Open Source Consulting company. We specialize in UI and Full Stack Architectures using HTML5, CSS, JavaScript and Java. We love HTML5, Angular, Bootstrap, Spring Boot, and especially JHipster.</description>
  <language>en-us</language>
  <copyright>Copyright 2026</copyright>
  <lastBuildDate>Mon, 30 Mar 2026 03:31:45 -0600</lastBuildDate>
  <generator>Apache Roller (incubating) 5.0.3 (1388864191739:dave)</generator>
        <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/google_s_mirror_of_maven</guid>
    <title>Google&apos;s Mirror of Maven Central 25% Faster</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/google_s_mirror_of_maven</link>
        <pubDate>Tue, 10 Nov 2015 00:13:51 -0700</pubDate>
    <category>Java</category>
    <category>dependencies</category>
    <category>googlecloudstorage</category>
    <category>mavencentral</category>
    <category>infoq</category>
    <category>maven</category>
            <description>&lt;p&gt;
Last week, &lt;a href=&quot;http://takari.io/2015/10/28/google-maven-central.html&quot;&gt;Takari announced that Google is Maven Central&apos;s New Best Friend&lt;/a&gt;. While writing a
    &lt;a href=&quot;http://www.infoq.com/news/2015/11/maven-central-at-google&quot;&gt;news article about this&lt;/a&gt; for
InfoQ, I decided to run a small test to see the speed of the default Maven Central versus the new Google Cloud Storage instance. This
micro benchmark didn&apos;t seem worthy of including in the article, but I think it&apos;s interesting to see the speed improvements I found.
&lt;/p&gt;
&lt;p&gt;
I ran &lt;code&gt;rm -rf ~/.m2/repository&lt;/code&gt;, then &lt;code&gt;mvn install&lt;/code&gt; with the default repository configured. I ran the commands again with
Google Cloud Storage. I found that the downloading of dependencies, compilation and running unit tests on
    &lt;a href=&quot;https://github.com/appfuse/appfuse/tree/master/web&quot;&gt;AppFuse&apos;s web projects&lt;/a&gt; averaged 4 minutes, 30 seconds.
With Google Cloud Storage, the same process averaged 3 minutes and 37 seconds. By my calculations, this means you speed up artifact resolution
for your Maven projects by 25% by switching to Google. To do that, create a &lt;code&gt;~/.m2/settings.xml&lt;/code&gt; file with
    the following contents.
    &lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;settings&amp;gt;
  &amp;lt;mirrors&amp;gt;
    &amp;lt;mirror&amp;gt;
      &amp;lt;id&amp;gt;google-maven-central&amp;lt;/id&amp;gt;
      &amp;lt;name&amp;gt;Google Maven Central&amp;lt;/name&amp;gt;
      &amp;lt;url&amp;gt;https://maven-central.storage.googleapis.com&amp;lt;/url&amp;gt;
      &amp;lt;mirrorOf&amp;gt;central&amp;lt;/mirrorOf&amp;gt;
    &amp;lt;/mirror&amp;gt;
  &amp;lt;/mirrors&amp;gt;
&amp;lt;/settings&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Benchmark Details&lt;/strong&gt;&lt;br&gt;
My tests were run on a Mac Pro (late 2013)
with a 3.5 GHz 6-Core Intel Xeon E5 processor and 32 GB of RAM. Bandwidth speeds during this test averaged 57 Mbps down,
6 Mbps up. Below are the timing numbers (in minutes) from my test:
&lt;/p&gt;
&lt;pre&gt;
Default: 4:33, 4:36, 4:32, 4:24, 4:09
Google: 5:13, 3:35, 2:15, 3:38, 3:39
&lt;/pre&gt;
&lt;p&gt;Google had some wide variances in its results, with five minutes and two minutes. Because of this, I dropped the
low and high numbers for each service before calculating the average. My math with raw numbers is below.
&lt;/p&gt;
&lt;pre&gt;
Default:
273, 276, 272, 264, 213 = 260, 4:20
276, 272, 264 = 270, 4:30

Google:
313, 215, 135, 218, 219 = 220, 3.66 = 3:40
215, 218, 219 = 3:37
&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://www.infoq.com/news/2015/11/maven-central-at-google#anch129463&quot;&gt;Chen Eric commented on the InfoQ article&lt;/a&gt;
    to note that Chinese programmers are blocked from using Google.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Jason Swank of Sonatype has done some more extensive benchmarking and &lt;a href=&quot;//raibledesigns.com/rd/entry/google_s_mirror_of_maven#comment-1447442881000&quot;&gt;found different results&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote class=&quot;quote&quot;&gt;
We found that average unprimed Google API (first mvn run) caching performed 30% slower than Maven Central. Primed Google API cache performance (second run) was 3% faster then Maven Central (second run). We also ran a number of cloud-based tests with similar results.
&lt;/blockquote&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_3_5_released</guid>
    <title>AppFuse 3.5 Released!</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_3_5_released</link>
        <pubDate>Fri, 20 Feb 2015 09:08:53 -0700</pubDate>
    <category>Java</category>
    <category>wicket</category>
    <category>java</category>
    <category>gwt</category>
    <category>springmvc</category>
    <category>springsecurity</category>
    <category>maven</category>
    <category>tapestry5</category>
    <category>javaee</category>
    <category>jsf</category>
    <category>struts2</category>
    <category>spring</category>
            <description>&lt;p&gt;
&lt;a href=&quot;http://appfuse.org&quot;&gt;&lt;img src=&quot;http://static.appfuse.org/images/appfuse-icon.gif&quot; class=&quot;picture&quot; style=&quot;border: 0&quot;&gt;&lt;/a&gt;
The AppFuse Team is pleased to announce the release of AppFuse 3.5. This release contains a number of improvements.&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;XML reduced by 8x in projects generated with AppFuse&lt;/li&gt;&lt;li&gt;CRUD generation&amp;nbsp;support for Wicket, as well as AppFuse Light archetypes (Spring Security, Spring FreeMarker and Stripes)&lt;/li&gt;&lt;li&gt;Upgraded Tapestry to 5.4&lt;/li&gt;&lt;li&gt;Integrated&amp;nbsp;Spring IO Platform for dependency management&lt;/li&gt;&lt;li&gt;Refactored unit tests to use JUnit 4&lt;/li&gt;&lt;li&gt;Renamed maven-warpath-plugin to warpath-maven-plugin&lt;/li&gt;&lt;li&gt;Upgraded to jWebUnit 3 for AppFuse Light integration tests&lt;/li&gt;&lt;li&gt;Updated all AppFuse Light modules to be up-to-date&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;For more details on specific changes
    see the &lt;a href=&quot;http://appfuse.org/display/APF/Release+Notes+3.5.0&quot;&gt;release notes&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;What is AppFuse?&lt;/strong&gt;&lt;br&gt;
    AppFuse is a full-stack framework for building web applications on the JVM. It was
    originally developed to eliminate the ramp-up time when building new web applications. Over
    the years, it has matured into a very testable and secure system for creating Java-based
    webapps.
&lt;/p&gt;
&lt;p&gt;Demos for this release can be viewed at &lt;a href=&quot;http://demo.appfuse.org/&quot;&gt;http://demo.appfuse.org&lt;/a&gt;. Please see
    the &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+QuickStart&quot; style=&quot;font-weight: bold&quot;&gt;QuickStart Guide&lt;/a&gt; to
    get started with this release. &lt;/p&gt;

&lt;p&gt;If you have questions about AppFuse, please read the &lt;a href=&quot;http://appfuse.org/display/APF/FAQ&quot;&gt;FAQ&lt;/a&gt; or join the
    &lt;a href=&quot;http://appfuse.org/display/APF/Mailing+Lists&quot;&gt;user mailing list&lt;/a&gt;. If you find any
    issues, please report them on the users mailing list. You can also post them to &lt;a href=&quot;http://stackoverflow.com/questions/tagged/appfuse&quot;&gt;Stack Overflow&lt;/a&gt; with the &quot;appfuse&quot; tag.&lt;/p&gt;

&lt;p&gt;Thanks to everyone for their help contributing patches, writing documentation and participating on the mailing
    lists.&lt;/p&gt;

&lt;p style=&quot;border-top: 1px dotted silver; padding-top: 5px; color: #666&quot;&gt;We greatly appreciate the help from &lt;a href=&quot;http://appfuse.org/display/APF/Sponsors&quot;&gt;our
    sponsors&lt;/a&gt;, particularly &lt;a href=&quot;http://www.atlassian.com/c/NPOS/10160&quot;&gt;Atlassian&lt;/a&gt;,
    &lt;a href=&quot;http://contegix.com/&quot;&gt;Contegix&lt;/a&gt;, and &lt;a href=&quot;http://www.jetbrains.com/&quot;&gt;JetBrains&lt;/a&gt;.
    Atlassian and Contegix are especially awesome:
    &lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_now_powered_by_contegix&quot;&gt;Atlassian has donated licenses to all
        its products and Contegix has donated an entire server&lt;/a&gt; to the AppFuse project. &lt;/p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_reduced</guid>
    <title>AppFuse, Reduced</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_reduced</link>
        <pubDate>Tue, 16 Dec 2014 06:03:31 -0700</pubDate>
    <category>Java</category>
    <category>java</category>
    <category>maven</category>
    <category>maintenance</category>
    <category>lessxml</category>
    <category>appfuse</category>
    <category>spring</category>
    <atom:summary type="html">&lt;p&gt;
In November, I had some time off between clients. To occupy my time, I exercised my body and brain a bit. I spent a couple hours a day exercising and a few hours a day working on
&lt;a href=&quot;http://appfuse.org&quot;&gt;AppFuse&lt;/a&gt;. AppFuse isn&apos;t used to start projects nearly as much as it once was. This makes sense since there&apos;s been a ton of innovation on the JVM and there&apos;s lots of
&lt;em&gt;get-started-quickly&lt;/em&gt; frameworks now. Among my favorites are Spring Boot, JHipster, Grails and Play.
&lt;p&gt;
    You can see that AppFuse&apos;s community activity has decreased quite a bit over the years by looking at its mailing list
    traffic.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
    &lt;a href=&quot;http://appfuse.markmail.org/&quot;
       title=&quot;AppFuse Mailing List Traffic, December 2014 by Matt Raible, on Flickr&quot;&gt;&lt;img
        src=&quot;https://farm8.staticflickr.com/7525/15825430580_0531875e59.jpg&quot; width=&quot;500&quot; 
        alt=&quot;AppFuse Mailing List Traffic, December 2014&quot;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
    Even though there&apos;s not a lot of users talking on the mailing list, it still seems to get quite a few downloads from
    Maven Central.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
    &lt;a href=&quot;https://www.flickr.com/photos/mraible/16011987392&quot;
       title=&quot;AppFuse Maven Central Stats, November 2014 by Matt Raible, on Flickr&quot;&gt;&lt;img
        src=&quot;https://farm8.staticflickr.com/7534/16011987392_442236433b.jpg&quot; width=&quot;500&quot; 
        alt=&quot;AppFuse Maven Central Stats, November 2014&quot;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
    I think the biggest value that AppFuse provides now is a learning tool for those who work on it. Also, it&apos;s a good place to
    show other developers how they can evolve with open source frameworks (e.g. Spring, Hibernate, JSF, Tapestry, Struts) over several years. Showing how
    we migrated to Spring MVC Test, for example, might be useful. The upcoming move to Spring Data instead of our
    Generic DAO solution might be interesting as well. 
&lt;/p&gt;
&lt;p&gt;
    Regardless of whether AppFuse is used a lot or not, it should be easy to maintain. Over the several weeks, I made some
    opinionated changes and achieved some pretty good progress on simplifying things and making the project easier to
    maintain. The previous structure has a lot of duplicate versions, properties and plugin configurations between
    different projects. I was able to leverage Maven&apos;s inheritance model to make a number of improvements:
&lt;/p&gt;</atom:summary>        <description>&lt;p&gt;
In November, I had some time off between clients. To occupy my time, I exercised my body and brain a bit. I spent a couple hours a day exercising and a few hours a day working on
&lt;a href=&quot;http://appfuse.org&quot;&gt;AppFuse&lt;/a&gt;. AppFuse isn&apos;t used to start projects nearly as much as it once was. This makes sense since there&apos;s been a ton of innovation on the JVM and there&apos;s lots of
&lt;em&gt;get-started-quickly&lt;/em&gt; frameworks now. Among my favorites are Spring Boot, JHipster, Grails and Play.
&lt;p&gt;
    You can see that AppFuse&apos;s community activity has decreased quite a bit over the years by looking at its mailing list
    traffic.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
    &lt;a href=&quot;http://appfuse.markmail.org/&quot;
       title=&quot;AppFuse Mailing List Traffic, December 2014 by Matt Raible, on Flickr&quot;&gt;&lt;img
        src=&quot;https://farm8.staticflickr.com/7525/15825430580_0531875e59.jpg&quot; width=&quot;500&quot; 
        alt=&quot;AppFuse Mailing List Traffic, December 2014&quot;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
    Even though there&apos;s not a lot of users talking on the mailing list, it still seems to get quite a few downloads from
    Maven Central.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
    &lt;a href=&quot;https://www.flickr.com/photos/mraible/16011987392&quot;
       title=&quot;AppFuse Maven Central Stats, November 2014 by Matt Raible, on Flickr&quot;&gt;&lt;img
        src=&quot;https://farm8.staticflickr.com/7534/16011987392_442236433b.jpg&quot; width=&quot;500&quot; 
        alt=&quot;AppFuse Maven Central Stats, November 2014&quot;&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
    I think the biggest value that AppFuse provides now is a learning tool for those who work on it. Also, it&apos;s a good place to
    show other developers how they can evolve with open source frameworks (e.g. Spring, Hibernate, JSF, Tapestry, Struts) over several years. Showing how
    we migrated to Spring MVC Test, for example, might be useful. The upcoming move to Spring Data instead of our
    Generic DAO solution might be interesting as well. 
&lt;/p&gt;
&lt;p&gt;
    Regardless of whether AppFuse is used a lot or not, it should be easy to maintain. Over the several weeks, I made some
    opinionated changes and achieved some pretty good progress on simplifying things and making the project easier to
    maintain. The previous structure has a lot of duplicate versions, properties and plugin configurations between
    different projects. I was able to leverage Maven&apos;s inheritance model to make a number of improvements:
&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Changed AppFuse&apos;s parent to be based on the &lt;a
        href=&quot;http://www.infoq.com/news/2014/07/springio-platform&quot;&gt;Spring IO Platform&lt;/a&gt;. This project
        is a dependency manager that defines version numbers for open source projects that work well with Spring.
    &lt;/li&gt;
    &lt;li&gt;Defined plugins, their versions and configurations in &lt;code&gt;&amp;lt;pluginManagement&gt;&lt;/code&gt;.&lt;/li&gt;
    &lt;li&gt;Defined dependencies, their versions and exclusions in &lt;code&gt;&amp;lt;dependencyManagement&gt;&lt;/code&gt;.&lt;/li&gt;
    &lt;li&gt;Simplified archetypes so new projects have minimal dependencies. For example, here&apos;s a basic project&apos;s &lt;code&gt;pom.xml&lt;/code&gt;:
    &lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
         xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&amp;gt;

    &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
    &amp;lt;groupId&amp;gt;com.company&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;springmvc-project&amp;lt;/artifactId&amp;gt;
    &amp;lt;packaging&amp;gt;war&amp;lt;/packaging&amp;gt;
    &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
    &amp;lt;name&amp;gt;AppFuse Spring MVC Application&amp;lt;/name&amp;gt;

    &amp;lt;parent&amp;gt;
        &amp;lt;groupId&amp;gt;org.appfuse&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;appfuse-web&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;3.5.0-SNAPSHOT&amp;lt;/version&amp;gt;
    &amp;lt;/parent&amp;gt;

    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;de.juplo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;hibernate4-maven-plugin&amp;lt;/artifactId&amp;gt;
            &amp;lt;/plugin&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;dbunit-maven-plugin&amp;lt;/artifactId&amp;gt;
            &amp;lt;/plugin&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;build-helper-maven-plugin&amp;lt;/artifactId&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;

    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.appfuse&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;appfuse-${web.framework}&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;${appfuse.version}&amp;lt;/version&amp;gt;
            &amp;lt;type&amp;gt;pom&amp;lt;/type&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;

    &amp;lt;properties&amp;gt;
        &amp;lt;amp.genericCore&amp;gt;true&amp;lt;/amp.genericCore&amp;gt;
        &amp;lt;amp.fullSource&amp;gt;false&amp;lt;/amp.fullSource&amp;gt;
        &amp;lt;dao.framework&amp;gt;hibernate&amp;lt;/dao.framework&amp;gt;
        &amp;lt;db.name&amp;gt;mydatabase&amp;lt;/db.name&amp;gt;
        &amp;lt;web.framework&amp;gt;spring&amp;lt;/web.framework&amp;gt;

        &amp;lt;!-- Framework/Plugin versions --&amp;gt;
        &amp;lt;appfuse.version&amp;gt;3.5.0-SNAPSHOT&amp;lt;/appfuse.version&amp;gt;
        &amp;lt;java.version&amp;gt;1.7&amp;lt;/java.version&amp;gt;
    &amp;lt;/properties&amp;gt;

    &amp;lt;profiles&amp;gt;
        &amp;lt;profile&amp;gt;
            &amp;lt;id&amp;gt;itest&amp;lt;/id&amp;gt;
            &amp;lt;build&amp;gt;
                &amp;lt;plugins&amp;gt;
                    &amp;lt;plugin&amp;gt;
                        &amp;lt;groupId&amp;gt;org.codehaus.cargo&amp;lt;/groupId&amp;gt;
                        &amp;lt;artifactId&amp;gt;cargo-maven2-plugin&amp;lt;/artifactId&amp;gt;
                    &amp;lt;/plugin&amp;gt;
                    &amp;lt;plugin&amp;gt;
                        &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
                        &amp;lt;artifactId&amp;gt;webtest-maven-plugin&amp;lt;/artifactId&amp;gt;
                    &amp;lt;/plugin&amp;gt;
                &amp;lt;/plugins&amp;gt;
            &amp;lt;/build&amp;gt;
        &amp;lt;/profile&amp;gt;
    &amp;lt;/profiles&amp;gt;

    &amp;lt;reporting&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;webtest-maven-plugin&amp;lt;/artifactId&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/reporting&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/pre&gt;
&lt;style type=&quot;text/css&quot;&gt;
    span.diffstat {
        white-space: nowrap;
        text-align: right;
        font-family: Helvetica, arial, freesans, clean, sans-serif, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;;
        color: #666;
        font-weight: bold;
        font-size: 12px;
        cursor: default;
    }

    span.diffstat .lines-added, span.diffstat .lines-deleted {
        display: inline-block;
        margin-left: 3px;
        font-weight: bold;
    }
&lt;/style&gt;
&lt;p&gt;
    The pull request for these changes says it all:
&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href=&quot;https://github.com/appfuse/appfuse/pull/20&quot;&gt;AppFuse&lt;/a&gt; &lt;span class=&quot;diffstat&quot;&gt;
          &lt;span class=&quot;lines-added&quot; style=&quot;color: #55a532&quot;&gt;
            &lt;span class=&quot;diffstat-icon&quot;&gt;+&lt;/span&gt;4,822
          &lt;/span&gt;
          &lt;span class=&quot;lines-deleted&quot; style=&quot;color: #bd2c00&quot;&gt;
            &lt;span class=&quot;diffstat-icon&quot;&gt;-&lt;/span&gt;14,369
          &lt;/span&gt;
        &lt;/span&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://github.com/appfuse/appfuse-light/pull/1&quot;&gt;AppFuse Light&lt;/a&gt; &lt;span class=&quot;diffstat&quot;&gt;
              &lt;span class=&quot;lines-added&quot; style=&quot;color: #55a532&quot;&gt;
                &lt;span class=&quot;diffstat-icon&quot;&gt;+&lt;/span&gt;776
              &lt;/span&gt;
              &lt;span class=&quot;lines-deleted&quot; style=&quot;color: #bd2c00&quot;&gt;
                &lt;span class=&quot;diffstat-icon&quot;&gt;-&lt;/span&gt;4,687
              &lt;/span&gt;

            &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&apos;s right, I was able to eliminate a good chunk of code without affecting any of AppFuse&apos;s functionality&lt;sup&gt;&lt;a
    href=&quot;http://raibledesigns.com/rd/entry/appfuse_reduced#footnote1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.
    I think we can all agree that less code == easier maintenance. This theme will continue as we work on future
    releases.
&lt;/p&gt;

&lt;p&gt;Other improvements include migrating all tests to use JUnit4, integrating Spring MVC Test, and configuring the
    surefire plugin to run tests in parallel. I also The &lt;a href=&quot;http://mojo.codehaus.org/build-helper-maven-plugin/&quot;&gt;build-helper-maven-plugin&lt;/a&gt;
    is now used to find open ports for Cargo to run and a lot of testing was done to ensure you can build/test multiple
    AppFuse-derived projects at the same time. Finally, I migrated to the &lt;a href=&quot;http://juplo.de/hibernate4-maven-plugin/&quot;&gt;hibernate4-maven-plugin&lt;/a&gt; and upgraded to Tapestry 5.4.&lt;/p&gt;

&lt;p&gt;In the next version of AppFuse, I plan to remove as
    much XML as possible - moving all of the configuration to Spring&apos;s JavaConfig. We&apos;ll also be moving to Java 8 as a
    minimum. I&apos;m even considering getting rid of all the pom.xml files in favor of another build language that requires
    less code. &lt;/p&gt;
&lt;p&gt;In other words, the upcoming 3.5 release will be the last release that supports Java 7 and uses Spring&apos;s XML for configuration. AppFuse 4.0 will strive for #NoXML.
   &lt;a href=&quot;http://appfuse.org/display/APF/Roadmap&quot;&gt;The project&apos;s roadmap&lt;/a&gt; has more details on additional
    hopes and dreams.&lt;/p&gt;

&lt;p&gt;We&apos;d love to hear your feedback on these change. Do you like the simplification theme? Are you OK with having AppFuse
    as a parent in your projects?
&lt;/p&gt;
&lt;p class=&quot;footnotes&quot; style=&quot;border-top: 1px dotted silver; padding-top: 5px; font-size: .9em&quot;&gt;
    &lt;a name=&quot;footnote1&quot;&gt;&lt;/a&gt;1. For project
    and code stats, see &lt;a href=&quot;https://www.openhub.net/p/appfuse/analyses/latest/languages_summary&quot;&gt;AppFuse on Open
    Hub&lt;/a&gt;.
&lt;/p&gt;
</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/developing_services_with_apache_camel1</guid>
    <title>Developing Services with Apache Camel - Part II: Creating and Testing Routes</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/developing_services_with_apache_camel1</link>
        <pubDate>Tue, 30 Sep 2014 10:05:38 -0600</pubDate>
    <category>Java</category>
    <category>java</category>
    <category>junit</category>
    <category>testing</category>
    <category>maven</category>
    <category>tomcat</category>
    <category>apachecamel</category>
    <category>spring</category>
    <category>microservices</category>
    <category>camel</category>
    <category>jenkins</category>
    <atom:summary type="html">&lt;p&gt;
    &lt;a href=&quot;http://camel.apache.org&quot;&gt;&lt;img src=&quot;http://camel.apache.org/images/camel-box-small.png&quot; height=&quot;150&quot;
                                           alt=&quot;Apache Camel&quot; class=&quot;picture&quot;&gt;&lt;/a&gt;
    This article is the second in a series on Apache Camel and how I used it to replace IBM Message Broker for a client.
    The first article, &lt;a href=&quot;http://raibledesigns.com/rd/entry/developing_services_with_apache_camel&quot;&gt;
    Developing Services with Apache Camel - Part I: The Inspiration&lt;/a&gt;, describes why I chose Camel for this project.
&lt;/p&gt;

&lt;p&gt;

&lt;p&gt;To make sure these new services correctly replaced existing services, a 3-step approach was used:&lt;/p&gt;
&lt;ol class=&quot;task-list&quot;&gt;
    &lt;li&gt;Write an integration test pointing to the old service.&lt;/li&gt;
    &lt;li&gt;Write the implementation and a unit test to prove it works.&lt;/li&gt;
    &lt;li&gt;Write an integration test pointing to the new service.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
    I chose to start by replacing the simplest service first. It was a SOAP Service that talked to a database to
    retrieve
    a value based on an input parameter. To learn more about Camel and how it works, I started by looking at the
    &lt;a href=&quot;http://camel.apache.org/cxf-tomcat-example.html&quot;&gt;CXF Tomcat Example&lt;/a&gt;. I learned that
    Camel is used to provide &lt;em&gt;routing&lt;/em&gt; of requests. Using its &lt;a href=&quot;http://camel.apache.org/cxf.html&quot;&gt;CXF
    component&lt;/a&gt;, it can easily produce SOAP web service
    endpoints. An end point is simply an interface, and Camel takes care of producing the implementation.
&lt;/p&gt;</atom:summary>        <description>&lt;p&gt;
    &lt;a href=&quot;http://camel.apache.org&quot;&gt;&lt;img src=&quot;http://camel.apache.org/images/camel-box-small.png&quot; height=&quot;150&quot;
                                           alt=&quot;Apache Camel&quot; class=&quot;picture&quot;&gt;&lt;/a&gt;
    This article is the second in a series on Apache Camel and how I used it to replace IBM Message Broker for a client.
    The first article, &lt;a href=&quot;http://raibledesigns.com/rd/entry/developing_services_with_apache_camel&quot;&gt;
    Developing Services with Apache Camel - Part I: The Inspiration&lt;/a&gt;, describes why I chose Camel for this project.
&lt;/p&gt;

&lt;p&gt;

&lt;p&gt;To make sure these new services correctly replaced existing services, a 3-step approach was used:&lt;/p&gt;
&lt;ol class=&quot;task-list&quot;&gt;
    &lt;li&gt;Write an integration test pointing to the old service.&lt;/li&gt;
    &lt;li&gt;Write the implementation and a unit test to prove it works.&lt;/li&gt;
    &lt;li&gt;Write an integration test pointing to the new service.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
    I chose to start by replacing the simplest service first. It was a SOAP Service that talked to a database to
    retrieve
    a value based on an input parameter. To learn more about Camel and how it works, I started by looking at the
    &lt;a href=&quot;http://camel.apache.org/cxf-tomcat-example.html&quot;&gt;CXF Tomcat Example&lt;/a&gt;. I learned that
    Camel is used to provide &lt;em&gt;routing&lt;/em&gt; of requests. Using its &lt;a href=&quot;http://camel.apache.org/cxf.html&quot;&gt;CXF
    component&lt;/a&gt;, it can easily produce SOAP web service
    endpoints. An end point is simply an interface, and Camel takes care of producing the implementation.
&lt;/p&gt;

&lt;h3 id=&quot;legacy-integration-test&quot;&gt;Legacy Integration Test&lt;/h3&gt;

&lt;p&gt;I started by writing a &lt;code&gt;LegacyDrugServiceTests&lt;/code&gt; integration test for the old drug service.
    I tried two different ways of testing, using WSDL-generated Java classes, as well as using JAX-WS&apos;s SOAP API.
    Finding the WSDL for the legacy service was difficult because IBM Message Broker doesn&apos;t expose it when adding
    &quot;?wsdl&quot; to the service&apos;s URL. Instead, I had to dig through the project files until I found it. Then I
    used the &lt;a href=&quot;http://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-java.html&quot;&gt;cxf-codegen-plugin&lt;/a&gt;
    to generate the web service client. Below is what one of the tests looked like that uses the JAX-WS API.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
@Test
public void sendGPIRequestUsingSoapApi() throws Exception {
    SOAPElement bodyChildOne = getBody(message).addChildElement(&quot;gpiRequest&quot;, &quot;m&quot;);
    SOAPElement bodyChildTwo = bodyChildOne.addChildElement(&quot;args0&quot;, &quot;m&quot;);
    bodyChildTwo.addChildElement(&quot;NDC&quot;, &quot;ax22&quot;).addTextNode(&quot;54561237201&quot;);
    SOAPMessage reply = connection.call(message, getUrlWithTimeout(SERVICE_NAME));
    if (reply != null) {
        Iterator itr = reply.getSOAPBody().getChildElements();
        Map resultMap = TestUtils.getResults(itr);
        assertEquals(&quot;66100525123130&quot;, resultMap.get(&quot;GPI&quot;));
    }
}
&lt;/pre&gt;
&lt;h3 id=&quot;implementation&quot;&gt;Implementing the Drug Service&lt;/h3&gt;

&lt;p&gt;In the last article, I mentioned I wanted no XML in the project. To facilitate this, I used Camel&apos;s
    &lt;a href=&quot;http://camel.apache.org/java-dsl.html&quot;&gt;Java DSL&lt;/a&gt; to define routes and Spring&apos;s
    &lt;a href=&quot;http://docs.spring.io/spring/docs/4.0.6.RELEASE/spring-framework-reference/htmlsingle/#beans-java&quot;&gt;JavaConfig&lt;/a&gt;
    to configure dependencies.
&lt;/p&gt;

&lt;p&gt;The first route I wrote was one that looked up a GPI (Generic Product Identifier) by NDC (National Drug Code).&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
@WebService
public interface DrugService {
    @WebMethod(operationName = &quot;gpiRequest&quot;)
    GpiResponse findGpiByNdc(GpiRequest request);
}
&lt;/pre&gt;
&lt;p&gt;
    To expose this as a web service endpoint with CXF, I needed to do two things:
&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Tell Spring how to configure CXF by importing &quot;classpath:META-INF/cxf/cxf.xml&quot; into a @Configuration class.&lt;/li&gt;
    &lt;li&gt;Configure CXF&apos;s Servlet so endpoints can be served up at a particular URL.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To satisfy item #1, I created a &lt;code&gt;CamelConfig&lt;/code&gt; class that extends &lt;a
        href=&quot;http://camel.apache.org/maven/camel-2.14.0/camel-spring-javaconfig/apidocs/org/apache/camel/spring/javaconfig/CamelConfiguration.html&quot;&gt;CamelConfiguration&lt;/a&gt;.
    This class allows Camel to be configured by Spring&apos;s JavaConfig. In it, I imported the CXF configuration, allowed
    tracing to be
    configured dynamically, and exposed my &lt;code&gt;application.properties&lt;/code&gt; to Camel. I also set it up (with &lt;code&gt;@ComponentScan&lt;/code&gt;)
    to look
    for Camel routes annotated with &lt;code&gt;@Component&lt;/code&gt;.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
@Configuration
@ImportResource(&quot;classpath:META-INF/cxf/cxf.xml&quot;)
@ComponentScan(&quot;com.raibledesigns.camel&quot;)
public class CamelConfig extends CamelConfiguration {
    @Value(&quot;${logging.trace.enabled}&quot;)
    private Boolean tracingEnabled;

    @Override
    protected void setupCamelContext(CamelContext camelContext) throws Exception {
        PropertiesComponent pc = new PropertiesComponent();
        pc.setLocation(&quot;classpath:application.properties&quot;);
        camelContext.addComponent(&quot;properties&quot;, pc);
        // see if trace logging is turned on
        if (tracingEnabled) {
            camelContext.setTracing(true);
        }
        super.setupCamelContext(camelContext);
    }

    @Bean
    public Tracer camelTracer() {
        Tracer tracer = new Tracer();
        tracer.setTraceExceptions(false);
        tracer.setTraceInterceptors(true);
        tracer.setLogName(&quot;com.raibledesigns.camel.trace&quot;);
        return tracer;
    }
}
&lt;/pre&gt;
&lt;p&gt;CXF has a servlet that&apos;s responsible for serving up its services at common path. To map CXF&apos;s servlet, I leveraged
    Spring&apos;s
    &lt;a href=&quot;http://docs.spring.io/autorepo/docs/spring-framework/4.0.x/javadoc-api/org/springframework/web/WebApplicationInitializer.html&quot;&gt;
        WebApplicationInitializer&lt;/a&gt; in an &lt;code&gt;AppInitializer&lt;/code&gt; class. I decided to serve up everything from a
    &lt;code&gt;/api/*&lt;/code&gt; base URL.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
package com.raibledesigns.camel.config;

import org.apache.cxf.transport.servlet.CXFServlet;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

public class AppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        servletContext.addListener(new ContextLoaderListener(getContext()));
        ServletRegistration.Dynamic servlet = servletContext.addServlet(&quot;CXFServlet&quot;, new CXFServlet());
        servlet.setLoadOnStartup(1);
        servlet.setAsyncSupported(true);
        servlet.addMapping(&quot;/api/*&quot;);
    }

    private AnnotationConfigWebApplicationContext getContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.setConfigLocation(&quot;com.raibledesigns.camel.config&quot;);
        return context;
    }
}
&lt;/pre&gt;
&lt;p&gt;
    To implement this web service with Camel, I created a &lt;code&gt;DrugRoute&lt;/code&gt; class that extends Camel&apos;s
    &lt;code&gt;RouteBuilder&lt;/code&gt;.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
@Component
public class DrugRoute extends RouteBuilder {
    private String uri = &quot;cxf:/drugs?serviceClass=&quot; + DrugService.class.getName();

    @Override
    public void configure() throws Exception {
        from(uri)
            .recipientList(simple(&quot;direct:${header.operationName}&quot;));
        from(&quot;direct:gpiRequest&quot;).routeId(&quot;gpiRequest&quot;)
            .process(new Processor() {
                public void process(Exchange exchange) throws Exception {
                    // get the ndc from the input
                    String ndc = exchange.getIn().getBody(GpiRequest.class).getNDC();
                    exchange.getOut().setBody(ndc);
                }
            })
            .to(&quot;sql:{{sql.selectGpi}}&quot;)
            .to(&quot;log:output&quot;)
            .process(new Processor() {
                public void process(Exchange exchange) throws Exception {
                    // get the gpi from the input
                    List&amp;lt;HashMap&amp;gt; data = (ArrayList&amp;lt;HashMap&amp;gt;) exchange.getIn().getBody();
                    DrugInfo drug = new DrugInfo();
                    if (data.size() &amp;gt; 0) {
                        drug = new DrugInfo(String.valueOf(data.get(0).get(&quot;GPI&quot;)));
                    }
                    GpiResponse response = new GpiResponse(drug);
                    exchange.getOut().setBody(response);
                }
            });
    }
}
&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;sql.selectGpi&lt;/code&gt; property is read from &lt;code&gt;src/main/resources/application.properties&lt;/code&gt; and looks
    as follows:&lt;/p&gt;
&lt;pre&gt;sql.selectGpi=select GPI from drugs where ndc = #?dataSource=ds.drugs&lt;/pre&gt;
&lt;p&gt;The &quot;ds.drugs&quot; reference is to a datasource that&apos;s created by Spring. From my
    &lt;code&gt;AppConfig&lt;/code&gt; class:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
@Configuration
@PropertySource(&quot;classpath:application.properties&quot;)
public class AppConfig {

    @Value(&quot;${ds.driver.db2}&quot;)
    private String jdbcDriverDb2;

    @Value(&quot;${ds.password}&quot;)
    private String jdbcPassword;

    @Value(&quot;${ds.url}&quot;)
    private String jdbcUrl;

    @Value(&quot;${ds.username}&quot;)
    private String jdbcUsername;

    @Bean(name = &quot;ds.drugs&quot;)
    public DataSource drugsDataSource() {
        return createDataSource(jdbcDriverDb2, jdbcUsername, jdbcPassword, jdbcUrl);
    }

    private BasicDataSource createDataSource(String driver, String username, String password, String url) {
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName(driver);
        ds.setUsername(username);
        ds.setPassword(password);
        ds.setUrl(url);
        ds.setMaxActive(100);
        ds.setMaxWait(1000);
        ds.setPoolPreparedStatements(true);
        return ds;
    }
}
&lt;/pre&gt;

&lt;h3 id=&quot;unit-testing&quot;&gt;Unit Testing&lt;/h3&gt;

&lt;p&gt;
    The hardest part about unit testing this route was figuring out how to use Camel&apos;s
    &lt;a href=&quot;http://camel.apache.org/testing.html&quot;&gt;testing support&lt;/a&gt;. I posted
    &lt;a href=&quot;http://camel.465427.n5.nabble.com/Mocking-SQL-results-in-a-route-td5752169.html&quot;&gt;a question&lt;/a&gt; to the
    Camel users mailing list in early June. Based on advice received, I bought
    &lt;a href=&quot;http://www.manning.com/ibsen/&quot;&gt;Camel in Action&lt;/a&gt;, read chapter 6 on testing and went to work.
    I wanted to eliminate the dependency on a datasource, so I used Camel&apos;s
    &lt;a href=&quot;http://camel.apache.org/advicewith.html&quot;&gt;AdviceWith&lt;/a&gt; feature to modify my route and intercept the
    SQL call. This allowed me to return pre-defined results and verify everything worked.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
@RunWith(CamelSpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = CamelSpringDelegatingTestContextLoader.class, classes = CamelConfig.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@UseAdviceWith
public class DrugRouteTests {

    @Autowired
    CamelContext camelContext;

    @Produce
    ProducerTemplate template;

    @EndpointInject(uri = &quot;mock:result&quot;)
    MockEndpoint result;

    static List&amp;lt;Map&amp;gt; results = new ArrayList&amp;lt;Map&amp;gt;() {{
        add(new HashMap&amp;lt;String, String&amp;gt;() {{
            put(&quot;GPI&quot;, &quot;123456789&quot;);
        }});
    }};

    @Before
    public void before() throws Exception {
        camelContext.setTracing(true);

        ModelCamelContext context = (ModelCamelContext) camelContext;
        RouteDefinition route = context.getRouteDefinition(&quot;gpiRequest&quot;);
        route.adviceWith(context, new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                interceptSendToEndpoint(&quot;sql:*&quot;).skipSendToOriginalEndpoint().process(new Processor() {
                    @Override
                    public void process(Exchange exchange) throws Exception {
                        exchange.getOut().setBody(results);
                    }
                });
            }
        });
        route.to(result);
        camelContext.start();
    }

    @Test
    public void testMockSQLEndpoint() throws Exception {
        result.expectedMessageCount(1);
        GpiResponse expectedResult = new GpiResponse(new DrugInfo(&quot;123456789&quot;));
        result.allMessages().body().contains(expectedResult);

        GpiRequest request = new GpiRequest();
        request.setNDC(&quot;123&quot;);
        template.sendBody(&quot;direct:gpiRequest&quot;, request);

        MockEndpoint.assertIsSatisfied(camelContext);
    }
}
&lt;/pre&gt;
&lt;p&gt;
    I found AdviceWith to be extremely useful as I developed more routes and tests in this project. I used its
    &lt;a href=&quot;http://camel.apache.org/advicewith.html#AdviceWith-UsingweaveById&quot;&gt;weaveById&lt;/a&gt; feature to intercept
    calls to stored procedures, replace steps in my routes and remove steps I didn&apos;t want to test. For example,
    in one route, there was a complicated workflow to interact with a customer&apos;s data.
&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Call a stored procedure in a remote database, which then inserts a record into a temp table.&lt;/li&gt;
    &lt;li&gt;Lookup that data using the value returned from the stored procedure.&lt;/li&gt;
    &lt;li&gt;Delete the record from the temp table.&lt;/li&gt;
    &lt;li&gt;Parse the data (as CSV) since the returned value is ~ delimited.&lt;/li&gt;
    &lt;li&gt;Convert the parsed data into objects, then do database inserts in a local database (if data doesn&apos;t exist).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To make matters worse, remote database access was restricted by IP address. This meant that, while developing, I
    couldn&apos;t
    even manually test from my local machine. To solve this, I used the following:
&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;code&gt;interceptSendToEndpoint(&quot;bean:*&quot;)&lt;/code&gt; to intercept the call to my stored procedure bean.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;weaveById(&quot;myJdbcProcessor&quot;).before()&lt;/code&gt; to replace the temp table lookup with a CSV file.&lt;/li&gt;
    &lt;li&gt;&lt;a href=&quot;https://code.google.com/p/mockito/&quot;&gt;Mockito&lt;/a&gt; to mock a JdbcTemplate that does the inserts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
    To figure out how to configure and execute stored procedures in a route, I used the &lt;a
        href=&quot;https://github.com/quephird/camel-stored-procedure&quot;&gt;
    camel-store-procedure project on GitHub&lt;/a&gt;. Mockito&apos;s
    &lt;a href=&quot;http://docs.mockito.googlecode.com/hg/org/mockito/ArgumentCaptor.html&quot;&gt;ArgumentCaptor&lt;/a&gt; also became very
    useful
    when developing a route that called a 3rd-party web service within a route. James Carr has
    &lt;a href=&quot;http://blog.james-carr.org/2009/09/28/mockito-verifying-details-of-an-object-passed-to-a-collaborator/&quot;&gt;more
        information&lt;/a&gt;
    on how you might use this to verify values on an argument.
&lt;/p&gt;

&lt;p&gt;
    To see if my tests were hitting all aspects of the code, I integrated the
    &lt;a href=&quot;http://mojo.codehaus.org/cobertura-maven-plugin/&quot;&gt;cobertura-maven-plugin&lt;/a&gt; for code coverage
    reports (generated by running &lt;code&gt;mvn site&lt;/code&gt;).
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;build&amp;gt;
    &amp;lt;plugins&amp;gt;
        &amp;lt;plugin&amp;gt;
            &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;cobertura-maven-plugin&amp;lt;/artifactId&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;instrumentation&amp;gt;
                    &amp;lt;excludes&amp;gt;
                        &amp;lt;exclude&amp;gt;**/model/*.class&amp;lt;/exclude&amp;gt;
                        &amp;lt;exclude&amp;gt;**/AppInitializer.class&amp;lt;/exclude&amp;gt;
                        &amp;lt;exclude&amp;gt;**/StoredProcedureBean.class&amp;lt;/exclude&amp;gt;
                        &amp;lt;exclude&amp;gt;**/SoapActionInterceptor.class&amp;lt;/exclude&amp;gt;
                    &amp;lt;/excludes&amp;gt;
                &amp;lt;/instrumentation&amp;gt;
                &amp;lt;check/&amp;gt;
            &amp;lt;/configuration&amp;gt;
            &amp;lt;version&amp;gt;2.6&amp;lt;/version&amp;gt;
        &amp;lt;/plugin&amp;gt;
...
&amp;lt;reporting&amp;gt;
    &amp;lt;plugins&amp;gt;
        &amp;lt;plugin&amp;gt;
            &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;cobertura-maven-plugin&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;2.6&amp;lt;/version&amp;gt;
        &amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;h3 id=&quot;integration-testing&quot;&gt;Integration Testing&lt;/h3&gt;

&lt;p&gt;
    Writing an integration test was fairly straightforward. I created a &lt;code&gt;DrugRouteITest&lt;/code&gt; class, a
    client using CXF&apos;s &lt;a href=&quot;https://cxf.apache.org/javadoc/latest/org/apache/cxf/jaxws/JaxWsProxyFactoryBean.html&quot;&gt;JaxWsProxyFactoryBean&lt;/a&gt;
    and called the method on the service.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public class DrugRouteITest {

    private static final String URL = &quot;http://localhost:8080/api/drugs&quot;;

    protected static DrugService createCXFClient() {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setBindingId(&quot;http://schemas.xmlsoap.org/wsdl/soap12/&quot;);
        factory.setServiceClass(DrugService.class);
        factory.setAddress(getTestUrl(URL));
        return (DrugService) factory.create();
    }

    @Test
    public void findGpiByNdc() throws Exception {
        // create input parameter
        GpiRequest input = new GpiRequest();
        input.setNDC(&quot;54561237201&quot;);

        // create the webservice client and send the request
        DrugService client = createCXFClient();
        GpiResponse response = client.findGpiByNdc(input);

        assertEquals(&quot;66100525123130&quot;, response.getDrugInfo().getGPI());
    }
}
&lt;/pre&gt;
&lt;p&gt;This integration test is only run after Tomcat has started and deployed the app. Unit tests are run by Maven&apos;s
    &lt;a href=&quot;http://maven.apache.org/surefire/maven-surefire-plugin/&quot;&gt;surefire-plugin&lt;/a&gt;, while integration tests are
    run by the &lt;a href=&quot;http://maven.apache.org/surefire/maven-failsafe-plugin/&quot;&gt;failsafe-plugin&lt;/a&gt;. An available
    Tomcat port is determined by the &lt;a href=&quot;http://mojo.codehaus.org/build-helper-maven-plugin/&quot;&gt;
        build-helper-maven-plugin&lt;/a&gt;. This port is set as a system property and read by the &lt;code&gt;getTestUrl()&lt;/code&gt;
    method call above.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public static String getTestUrl(String url) {
    if (System.getProperty(&quot;tomcat.http.port&quot;) != null) {
        url = url.replace(&quot;8080&quot;, System.getProperty(&quot;tomcat.http.port&quot;));
    }
    return url;
}
&lt;/pre&gt;
&lt;p&gt;Below are the relevant bits from
    &lt;code&gt;pom.xml&lt;/code&gt; that determines when to start/stop Tomcat, as well as which tests to run. &lt;/p&gt;

&lt;p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.tomcat.maven&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;tomcat7-maven-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.2&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;path&amp;gt;/&amp;lt;/path&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;id&amp;gt;start-tomcat&amp;lt;/id&amp;gt;
            &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;run&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;fork&amp;gt;true&amp;lt;/fork&amp;gt;
                &amp;lt;port&amp;gt;${tomcat.http.port}&amp;lt;/port&amp;gt;
            &amp;lt;/configuration&amp;gt;
        &amp;lt;/execution&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;id&amp;gt;stop-tomcat&amp;lt;/id&amp;gt;
            &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;shutdown&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.17&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;excludes&amp;gt;
            &amp;lt;exclude&amp;gt;**/*IT*.java&amp;lt;/exclude&amp;gt;
            &amp;lt;exclude&amp;gt;**/Legacy**.java&amp;lt;/exclude&amp;gt;
        &amp;lt;/excludes&amp;gt;
        &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*Tests.java&amp;lt;/include&amp;gt;
            &amp;lt;include&amp;gt;**/*Test.java&amp;lt;/include&amp;gt;
        &amp;lt;/includes&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-failsafe-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.17&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*IT*.java&amp;lt;/include&amp;gt;
        &amp;lt;/includes&amp;gt;
        &amp;lt;systemProperties&amp;gt;
            &amp;lt;tomcat.http.port&amp;gt;${tomcat.http.port}&amp;lt;/tomcat.http.port&amp;gt;
        &amp;lt;/systemProperties&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;integration-test&amp;lt;/goal&amp;gt;
                &amp;lt;goal&amp;gt;verify&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;The most useful part of integration testing came when I copied one of my legacy tests into it and started verifying
    backwards compatibility. Since we wanted to replace existing services, and require no client changes, I had to make
    the XML request and response match. &lt;a href=&quot;http://www.charlesproxy.com&quot;&gt;Charles&lt;/a&gt; was very useful for this
    exercise,
    letting me inspect the request/response and tweak things to match. The following JAX-WS annotations allowed me to
    change the XML
    element names and achieve backward compatibility.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;code&gt;@BindingType(SOAPBinding.SOAP12HTTP_BINDING)&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;@WebResult(name = &quot;return&quot;, targetNamespace = &quot;...&quot;)&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;@ResponseWrapper(localName = &quot;gpiResponse&quot;)&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;@WebParam(name = &quot;args0&quot;, targetNamespace = &quot;...&quot;)&lt;/code&gt;&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;@XmlElement(name = &quot;...&quot;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;jenkins-and-continuous-deployment&quot;&gt;Continuous Integration and Deployment&lt;/h3&gt;

&lt;p&gt;My next item of business was configuring a job in &lt;a href=&quot;http://jenkins-ci.org/&quot;&gt;Jenkins&lt;/a&gt; to continually test
    and deploy. Getting all the tests to pass was easy, and deploying to Tomcat was simple enough thanks to the
    &lt;a href=&quot;https://wiki.jenkins-ci.org/display/JENKINS/Deploy+Plugin&quot;&gt;Deploy Plugin&lt;/a&gt; and
    &lt;a href=&quot;http://paxcel.net/blog/automation-of-warear-deployment-using-jenkins/&quot;&gt;this article&lt;/a&gt;. However, after a
    few deploys, Tomcat would throw OutOfMemory exceptions. Therefore, I ended up creating a second &quot;deploy&quot; job that
    stops Tomcat, copies the successfully-built WAR to $CATALINA_HOME/webapps, removes $CATALINA_HOME/webapps/ROOT and
    restarts Tomcat. I used Jenkins &quot;Execute shell&quot; feature to configure these three steps.
    I was pleased to find my &lt;a
            href=&quot;http://raibledesigns.com/tomcat/boot-howto.html&quot;&gt;&lt;code&gt;/etc/init.d/tomcat&lt;/code&gt;&lt;/a&gt;
    script still worked for starting Tomcat at boot time and providing convenient start/stop commands.
&lt;/p&gt;

&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;

&lt;p&gt;
    This article shows you how I implemented and tested a simple Apache Camel route. The route described
    only does a simple database lookup, but you can see how Camel&apos;s testing support allows you to mock results and concentrate
    on developing your route logic. I found its testing framework very useful and not well documented, so hopefully this
    article helps to fix that. In the &lt;a href=&quot;http://raibledesigns.com/rd/entry/developing_services_with_apache_camel2&quot;&gt;next article&lt;/a&gt;, I&apos;ll talk about upgrading to Spring 4, integrating Spring Boot and
    our team&apos;s microservice deployment discussions.
&lt;/p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_3_0_released</guid>
    <title>AppFuse 3.0 Released!</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_3_0_released</link>
        <pubDate>Mon, 23 Dec 2013 14:31:15 -0700</pubDate>
    <category>Java</category>
    <category>spring</category>
    <category>primefaces</category>
    <category>wicket</category>
    <category>java</category>
    <category>bootstrap3</category>
    <category>maven</category>
    <category>spring4</category>
    <category>appfuse</category>
            <description>&lt;p&gt;
&lt;a href=&quot;http://appfuse.org&quot;&gt;&lt;img src=&quot;//static.appfuse.org/images/appfuse-icon.gif&quot; class=&quot;picture&quot; style=&quot;border: 0&quot;&gt;&lt;/a&gt;
The AppFuse Team is pleased to announce the release of AppFuse 3.0. This release is AppFuse&apos;s first release as a &lt;a href=&quot;http://raibledesigns.com/rd/entry/happy_10_year_appfuse&quot;&gt;10-year old&lt;/a&gt; and includes a whole slew of improvements.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Java 7 and Maven 3 are now minimal requirements&lt;/li&gt;
    &lt;li&gt;Replaced MyFaces and Tomahawk with PrimeFaces for JSF&lt;br&gt;
        &lt;ul&gt;
            &lt;li&gt;Removed SiteMesh in favor of JSF&apos;s built-in layout support&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;Added Wicket support&lt;/li&gt;
    &lt;li&gt;Migrated from jMock to Mockito for tests&lt;/li&gt;
    &lt;li&gt;Integrated wro4j and WebJars&lt;/li&gt;
    &lt;li&gt;Migrated to Bootstrap 3 and defaulted to Bootswatch&apos;s &lt;a href=&quot;http://bootswatch.com/spacelab/&quot;&gt;Spacelab
        theme&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In addition, this release includes upgrades to all dependencies to bring them up-to-date with their latest
    releases. Most notable are Spring 4, Spring Security 3.2 and Bootstrap 3. For more details on specific changes
    see the &lt;a href=&quot;http://appfuse.org/display/APF/Release+Notes+3.0.0&quot;&gt;release notes&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;quote&quot;&gt;&lt;strong&gt;What is AppFuse?&lt;/strong&gt;&lt;br&gt;

    AppFuse is a full-stack framework for building web applications on the JVM. It was
    originally developed to eliminate the ramp-up time when building new web applications. Over
    the years, it has matured into a very testable and secure system for creating Java-based
    webapps.
&lt;/p&gt;
&lt;p&gt;Demos for this release can be viewed at &lt;a href=&quot;http://demo.appfuse.org/&quot;&gt;http://demo.appfuse.org&lt;/a&gt;. Please see
    the &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+QuickStart&quot; style=&quot;font-weight: bold&quot;&gt;QuickStart Guide&lt;/a&gt; to
    get started with this release. &lt;/p&gt;

&lt;p&gt;If you have questions about AppFuse, please read the &lt;a href=&quot;http://appfuse.org/display/APF/FAQ&quot;&gt;FAQ&lt;/a&gt; or join the
    &lt;a href=&quot;http://appfuse.org/display/APF/Mailing+Lists&quot;&gt;user mailing list&lt;/a&gt;. If you find any
    issues, please report them on the users mailing list. You can also post them to &lt;a href=&quot;http://stackoverflow.com/questions/tagged/appfuse&quot;&gt;Stack Overflow&lt;/a&gt; with the &quot;appfuse&quot; tag.&lt;/p&gt;

&lt;p&gt;Thanks to everyone for their help contributing patches, writing documentation and participating on the mailing
    lists.&lt;/p&gt;

&lt;p style=&quot;border-top: 1px dotted silver; padding-top: 5px; color: #666&quot;&gt;We greatly appreciate the help from &lt;a href=&quot;http://appfuse.org/display/APF/Sponsors&quot;&gt;our
    sponsors&lt;/a&gt;, particularly &lt;a href=&quot;http://www.atlassian.com/c/NPOS/10160&quot;&gt;Atlassian&lt;/a&gt;,
    &lt;a href=&quot;http://contegix.com/&quot;&gt;Contegix&lt;/a&gt;, and &lt;a href=&quot;http://www.jetbrains.com/&quot;&gt;JetBrains&lt;/a&gt;.
    Atlassian and Contegix are especially awesome:
    &lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_now_powered_by_contegix&quot;&gt;Atlassian has donated licenses to all
        its products and Contegix has donated an entire server&lt;/a&gt; to the AppFuse project. &lt;/p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/a_webapp_makeover_with_spring</guid>
    <title>A Webapp Makeover with Spring 4 and Spring Boot</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/a_webapp_makeover_with_spring</link>
        <pubDate>Wed, 11 Dec 2013 12:47:15 -0700</pubDate>
    <category>Java</category>
    <category>spring4</category>
    <category>maven</category>
    <category>jersey</category>
    <category>springboot</category>
    <category>spring</category>
    <atom:summary type="html">&lt;p&gt;A typical Maven and Spring web application has a fair amount of XML and 
verbosity to it. Add in Jersey and Spring Security and you can have hundreds of lines of 
XML before you even start to write your Java code. As part of a recent project,
I was tasked with upgrading a webapp like this to use Spring 4 and 
&lt;a href=&quot;http://projects.spring.io/spring-boot/&quot;&gt;Spring Boot&lt;/a&gt;. I also figured I&apos;d try to minimize the XML.&lt;/p&gt; 
&lt;p&gt;This is my story on how I upgraded to Spring 4, Jersey 2, Java 8 and Spring Boot 0.5.0 M6. 
&lt;/p&gt;
&lt;p&gt;When I started, the app was using Spring 3.2.5, Spring Security 3.1.4 and Jersey 1.18. The
pom.xml had four Jersey dependencies, three Spring dependencies and three Spring Security
dependencies, along with a number of exclusions for &quot;jersey-spring&quot;.&lt;/p&gt;
&lt;p id=&quot;spring4&quot;&gt;&lt;strong&gt;Upgrading to Spring 4&lt;/strong&gt;&lt;br/&gt;
Upgrading to Spring 4 was easy, I changed the version property to 4.0.0.RC2 and added the new 
Spring &lt;a href=&quot;http://spring.io/blog/2013/12/03/spring-framework-4-0-rc2-available&quot;&gt;bill of materials&lt;/a&gt;
to my pom.xml. I also add the Spring milestone repo since Spring 4 won&apos;t be released to Maven central
until tomorrow.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;dependencyManagement&amp;gt;
    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-framework-bom&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;${spring.framework.version}&amp;lt;/version&amp;gt;
            &amp;lt;type&amp;gt;pom&amp;lt;/type&amp;gt;
            &amp;lt;scope&amp;gt;import&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;
&amp;lt;/dependencyManagement&amp;gt;

&amp;lt;repositories&amp;gt;
    &amp;lt;repository&amp;gt;
        &amp;lt;id&amp;gt;spring-milestones&amp;lt;/id&amp;gt;
        &amp;lt;url&amp;gt;http://repo.spring.io/milestone&amp;lt;/url&amp;gt;
        &amp;lt;snapshots&amp;gt;
            &amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;
        &amp;lt;/snapshots&amp;gt;
    &amp;lt;/repository&amp;gt;
&amp;lt;/repositories&amp;gt;
&lt;/pre&gt;</atom:summary>        <description>&lt;p&gt;A typical Maven and Spring web application has a fair amount of XML and 
verbosity to it. Add in Jersey and Spring Security and you can have hundreds of lines of 
XML before you even start to write your Java code. As part of a recent project,
I was tasked with upgrading a webapp like this to use Spring 4 and 
&lt;a href=&quot;http://projects.spring.io/spring-boot/&quot;&gt;Spring Boot&lt;/a&gt;. I also figured I&apos;d try to minimize the XML.&lt;/p&gt; 
&lt;p&gt;This is my story on how I upgraded to Spring 4, Jersey 2, Java 8 and Spring Boot 0.5.0 M6. 
&lt;/p&gt;
&lt;p&gt;When I started, the app was using Spring 3.2.5, Spring Security 3.1.4 and Jersey 1.18. The
pom.xml had four Jersey dependencies, three Spring dependencies and three Spring Security
dependencies, along with a number of exclusions for &quot;jersey-spring&quot;.&lt;/p&gt;
&lt;p id=&quot;spring4&quot;&gt;&lt;strong&gt;Upgrading to Spring 4&lt;/strong&gt;&lt;br/&gt;
Upgrading to Spring 4 was easy, I changed the version property to 4.0.0.RC2 and added the new 
Spring &lt;a href=&quot;http://spring.io/blog/2013/12/03/spring-framework-4-0-rc2-available&quot;&gt;bill of materials&lt;/a&gt;
to my pom.xml. I also add the Spring milestone repo since Spring 4 won&apos;t be released to Maven central
until tomorrow.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;dependencyManagement&amp;gt;
    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-framework-bom&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;${spring.framework.version}&amp;lt;/version&amp;gt;
            &amp;lt;type&amp;gt;pom&amp;lt;/type&amp;gt;
            &amp;lt;scope&amp;gt;import&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;
&amp;lt;/dependencyManagement&amp;gt;

&amp;lt;repositories&amp;gt;
    &amp;lt;repository&amp;gt;
        &amp;lt;id&amp;gt;spring-milestones&amp;lt;/id&amp;gt;
        &amp;lt;url&amp;gt;http://repo.spring.io/milestone&amp;lt;/url&amp;gt;
        &amp;lt;snapshots&amp;gt;
            &amp;lt;enabled&amp;gt;true&amp;lt;/enabled&amp;gt;
        &amp;lt;/snapshots&amp;gt;
    &amp;lt;/repository&amp;gt;
&amp;lt;/repositories&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Next, I removed all the references to ${spring.framework.version} in dependencies since it&apos;d 
be controlled by &lt;a href=&quot;http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management&quot;&gt;
Maven&apos;s dependency management feature&lt;/a&gt;. 
&lt;/p&gt;
&lt;pre class=&quot;brush: diff&quot;&gt;
     &amp;lt;dependency&amp;gt;
         &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
         &amp;lt;artifactId&amp;gt;spring-web&amp;lt;/artifactId&amp;gt;
-        &amp;lt;version&amp;gt;${spring.framework.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
I also changed to use Maven 3&apos;s &lt;a href=&quot;http://maven.apache.org/pom.html#Exclusions&quot;&gt;wildcard syntax&lt;/a&gt; to exclude multiple 
dependencies.&lt;/p&gt;
&lt;pre class=&quot;brush: diff&quot;&gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;com.sun.jersey.contribs&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;jersey-spring&amp;lt;/artifactId&amp;gt;
        &amp;lt;exclusions&amp;gt;
             &amp;lt;exclusion&amp;gt;
                 &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
-                    &amp;lt;artifactId&amp;gt;spring&amp;lt;/artifactId&amp;gt;
-                &amp;lt;/exclusion&amp;gt;
-                &amp;lt;exclusion&amp;gt;
-                    &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
-                    &amp;lt;artifactId&amp;gt;spring-core&amp;lt;/artifactId&amp;gt;
-                &amp;lt;/exclusion&amp;gt;
-                &amp;lt;exclusion&amp;gt;
-                    &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
-                    &amp;lt;artifactId&amp;gt;spring-web&amp;lt;/artifactId&amp;gt;
-                &amp;lt;/exclusion&amp;gt;
-                &amp;lt;exclusion&amp;gt;
-                    &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
-                    &amp;lt;artifactId&amp;gt;spring-beans&amp;lt;/artifactId&amp;gt;
-                &amp;lt;/exclusion&amp;gt;
-                &amp;lt;exclusion&amp;gt;
-                    &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
-                    &amp;lt;artifactId&amp;gt;spring-context&amp;lt;/artifactId&amp;gt;
+                    &amp;lt;artifactId&amp;gt;*&amp;lt;/artifactId&amp;gt;
             &amp;lt;/exclusion&amp;gt;
         &amp;lt;/exclusions&amp;gt;
     &amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;p&gt;I confirmed the upgrade worked by running &quot;mvn dependency:tree | grep spring&quot;, followed by &quot;mvn jetty:run&quot; and viewing the app in my browser. &lt;/p&gt;
&lt;p id=&quot;jersey2&quot;&gt;&lt;strong&gt;Upgrading to Jersey 2&lt;/strong&gt;&lt;br/&gt;
The next item I tackled was upgrading to Jersey 2.4.1. I changed the version number in my pom.xml, then added the Jersey BOM.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.glassfish.jersey&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jersey-bom&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${jersey.version}&amp;lt;/version&amp;gt;
    &amp;lt;type&amp;gt;pom&amp;lt;/type&amp;gt;
    &amp;lt;scope&amp;gt;import&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
You might ask &quot;why Jersey?&quot; if we already have Spring MVC and its REST support? You might also ask why not Play or Grails instead of a Java + Spring stack? For this particular project, I recommended technology options, and these were certainly among them. However, the team chose differently and I support their decision. The project is 
creating an iOS app, as well as a responsive HTML5 mobile/desktop app. We figured we had enough risk with new technologies on the front-end that we should play it a bit safer on the backend. To make the backend work a bit sexier, we&apos;ve decided to allow Spring 4, Java 8 and possibly some reactive principles.&lt;/p&gt;
&lt;p&gt;Next, I changed from the old &lt;i&gt;com.sun.jersey&lt;/i&gt; dependencies to &lt;i&gt;org.glassfish.jersey&lt;/i&gt; and removed jersey-spring. &lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.glassfish.jersey.containers&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jersey-container-servlet&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.glassfish.jersey.media&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jersey-media-json-jackson&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
The last thing I needed to do was change the servlet-class and param-name in web.xml:&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;servlet&amp;gt;
    &amp;lt;servlet-name&amp;gt;jersey-servlet&amp;lt;/servlet-name&amp;gt;
    &amp;lt;servlet-class&amp;gt;org.glassfish.jersey.servlet.ServletContainer&amp;lt;/servlet-class&amp;gt;
    &amp;lt;init-param&amp;gt;
        &amp;lt;param-name&amp;gt;jersey.config.server.provider.packages&amp;lt;/param-name&amp;gt;
        &amp;lt;param-value&amp;gt;com.raibledesigns.boot.service&amp;lt;/param-value&amp;gt;
    &amp;lt;/init-param&amp;gt;
    &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
&amp;lt;/servlet&amp;gt;
&lt;/pre&gt;
&lt;p id=&quot;java8&quot;&gt;&lt;strong&gt;Requiring Java 8&lt;/strong&gt;&lt;br/&gt;
Requiring Java 8 to compile was easy enough. I added the maven-compiler-plugin to enforce a minimum version.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;3.1&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;source&amp;gt;1.8&amp;lt;/source&amp;gt;
        &amp;lt;target&amp;gt;1.8&amp;lt;/target&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;&lt;p&gt;I &lt;a href=&quot;https://jdk8.java.net/download.html&quot;&gt;downloaded the latest Java 8 SDK&lt;/a&gt; and installed it. Then I set my JAVA_HOME to use it.&lt;/p&gt;
&lt;pre class=&quot;brush: shell&quot;&gt;
export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
&lt;/pre&gt;
&lt;p id=&quot;boot&quot;&gt;&lt;strong&gt;Integrating Spring Boot&lt;/strong&gt;&lt;br/&gt;
I learned about Spring Boot a few weeks ago &lt;a href=&quot;http://raibledesigns.com/rd/entry/devoxx_2013_a_nordic_countries&quot;&gt;at Devoxx&lt;/a&gt;. &lt;a href=&quot;http://www.joshlong.com/&quot;&gt;Josh Long&lt;/a&gt; gave me a 3-minute demo at the speaker&apos;s dinner and showed me enough to pique my interest. To integrate it into my project, I started with the &lt;a href=&quot;http://projects.spring.io/spring-boot/#quick-start&quot;&gt;Quick Start&lt;/a&gt;. I added the boot-parent, dependencies for web, security and actuator (logging, metrics, etc.) and the Maven plugin. I removed all the Spring and Spring Security dependencies.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;parent&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-starter-parent&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;0.5.0.M6&amp;lt;/version&amp;gt;
&amp;lt;/parent&amp;gt;
...
&amp;lt;pluginRepositories&amp;gt;
    &amp;lt;pluginRepository&amp;gt;
        &amp;lt;id&amp;gt;spring-milestones&amp;lt;/id&amp;gt;
        &amp;lt;url&amp;gt;http://repo.spring.io/milestone&amp;lt;/url&amp;gt;
    &amp;lt;/pluginRepository&amp;gt;
&amp;lt;/pluginRepositories&amp;gt;
...
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-starter-web&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-starter-security&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-starter-actuator&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;
...
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-maven-plugin&amp;lt;/artifactId&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Upon restarting my app, I got an error about spring-security.xml using a 3.1 XSD. I fixed it by changing to 3.2. Next, I wanted to eliminate web.xml. First of all, I created an &lt;code&gt;ApplicationInitializer&lt;/code&gt; so the WAR could be started from the command line.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
package com.raibledesigns.boot.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class ApplicationInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(ApplicationInitializer.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(ApplicationInitializer.class, args);
    }
}
&lt;/pre&gt;
&lt;p&gt;However, after adding this, I received the following error on startup:&lt;/p&gt;
&lt;pre class=&quot;brush: shell&quot;&gt;
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
&apos;org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor&apos;: 
Invocation of init method failed; nested exception is 
java.lang.AbstractMethodError: org.hibernate.validator.internal.engine.ConfigurationImpl
.getDefaultParameterNameProvider()Ljavax/validation/ParameterNameProvider;
&lt;/pre&gt;
&lt;p&gt;Adding hibernate-validator as a dependency solved this problem:&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.hibernate&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;hibernate-validator&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;p&gt;To configure Spring Security without web.xml and spring-security.xml, I created &lt;code&gt;WebSecurityConfig.java&lt;/code&gt;:
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
package com.raibledesigns.boot.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
@Order(Ordered.LOWEST_PRECEDENCE - 6)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers(&quot;/&quot;, &quot;/home&quot;).permitAll()
                .antMatchers(&quot;/v1.0/**&quot;).hasRole(&quot;USER&quot;)
                .anyRequest().authenticated();
        http.httpBasic().realmName(&quot;My API&quot;);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        authManagerBuilder.inMemoryAuthentication()
                .withUser(&quot;test&quot;).password(&quot;test123&quot;).roles(&quot;USER&quot;);
    }
}
&lt;/pre&gt;
&lt;p&gt;To configure Jersey without web.xml, I created a &lt;code&gt;JerseyConfig&lt;/code&gt; class:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
package com.raibledesigns.boot.config;

import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;

import javax.ws.rs.ApplicationPath;

@ApplicationPath(&quot;/v1.0&quot;)
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        packages(&quot;com.raibledesigns.boot.service&quot;);
        property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
        property(ServerProperties.JSON_PROCESSING_FEATURE_DISABLE, false);
        property(ServerProperties.MOXY_JSON_FEATURE_DISABLE, true);
        property(ServerProperties.WADL_FEATURE_DISABLE, true);
        register(LoggingFilter.class);
        register(JacksonFeature.class);
    }
}
&lt;/pre&gt;
&lt;p&gt;Finally, I created &lt;code&gt;MvcConfig.java&lt;/code&gt; to set the welcome page.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
package com.raibledesigns.boot.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController(&quot;/&quot;).setViewName(&quot;index&quot;);
    }
}
&lt;/pre&gt;
&lt;p&gt;To cleanup, I deleted &lt;code&gt;src/main/webapp/WEB-INF&lt;/code&gt; and created &lt;code&gt;src/main/resources/logback.xml&lt;/code&gt;:
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;configuration&amp;gt;
    &amp;lt;include resource=&quot;org/springframework/boot/logging/logback/base.xml&quot;/&amp;gt;
    &amp;lt;logger name=&quot;org.springframework.boot&quot; level=&quot;INFO&quot;/&amp;gt;
    &amp;lt;logger name=&quot;org.springframework.security&quot; level=&quot;ERROR&quot;/&amp;gt;
&amp;lt;/configuration&amp;gt;
&lt;/pre&gt;&lt;p&gt;Since Boot doesn&apos;t support JSP out-of-the-box, I renamed my index.jsp file to index.html and changed the URL in it to point to &quot;/v1.0/hello&quot;. I was pleased to see that everything worked nicely. I learned shortly after that I could remove the Spring BOM since Spring Boot &lt;a href=&quot;https://twitter.com/rob_winch/status/410609696639184896&quot;&gt;uses a &amp;lt;spring.version&amp;gt; property to control its Spring version&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;The only issue I found is when started the app with &quot;mvn package &amp;&amp; java -jar target/app.war&quot;, it failed to initialize Jersey. I tried adding a @Bean for the servlet:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
@Bean
public ServletRegistrationBean jerseyServlet() {
    ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), &quot;/v1.0/*&quot;);
    registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyConfig.class.getName());
    return registration;
}
&lt;/pre&gt;
&lt;p&gt;Unfortunately, when running it using &quot;java -jar&quot;, I get the following error:
&lt;/p&gt;
&lt;pre class=&quot;brush: shell&quot;&gt;
org.glassfish.hk2.api.MultiException: A MultiException has 1 exceptions.  They are:
1. org.glassfish.jersey.server.internal.scanning.ResourceFinderException: 
java.io.FileNotFoundException: /.../target/app.war!/WEB-INF/classes (No such file or directory)
	at org.jvnet.hk2.internal.Utilities.justCreate(Utilities.java:869)
	at org.jvnet.hk2.internal.ServiceLocatorImpl.create(ServiceLocatorImpl.java:814)
	at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:906)
	at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:898)
	at org.glassfish.jersey.server.ApplicationHandler.createApplication(ApplicationHandler.java:300)
	at org.glassfish.jersey.server.ApplicationHandler.&amp;lt;init&amp;gt;(ApplicationHandler.java:279)
	at org.glassfish.jersey.servlet.WebComponent.&amp;lt;init&amp;gt;(WebComponent.java:302)
&lt;/pre&gt;
&lt;p&gt;
This seems strange since there is a WEB-INF/classes in my WAR. Regardless, this is not a Boot problem per se, but more of a Jersey issue. From one of the Boot developers:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
The whole idea with Boot is that servlets are just a transport - they are a means to an end, and hopefully not the only one - the &quot;container&quot; is Spring, not the servlet container. We probably could add some form of support for SCI but only by hacking the containers since the spec really doesn&apos;t allow for much control of their lifecycle. It hasn&apos;t been a priority so far.
&lt;/p&gt;
&lt;p id=&quot;summary&quot;&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br/&gt;
I hope this article is useful to see how you to upgrade your Java webapps to use Spring 4 and Spring Boot. I&apos;ve created a &lt;a href=&quot;https://github.com/mraible/boot-makeover&quot;&gt;boot-makeover project on GitHub&lt;/a&gt; with all the code mentioned. You can also &lt;a href=&quot;https://github.com/mraible/boot-makeover/commits/master&quot;&gt;view the commits&lt;/a&gt; for each step. &lt;/p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_light_2_2_1</guid>
    <title>AppFuse Light 2.2.1 Released!</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_light_2_2_1</link>
        <pubDate>Thu, 24 Jan 2013 19:43:20 -0700</pubDate>
    <category>Java</category>
    <category>hibernate</category>
    <category>spring</category>
    <category>java</category>
    <category>appfuse</category>
    <category>security</category>
    <category>appfuse-light</category>
    <category>maven</category>
            <description>In December, the &lt;a href=&quot;http://appfuse.org&quot;&gt;AppFuse&lt;/a&gt; Team &lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_2_2_1_released&quot;&gt;released 2.2.1&lt;/a&gt;. Right before that release, I decided to wait on enhancing its &quot;light&quot; modules, a.k.a. &lt;a href=&quot;https://github.com/appfuse/appfuse-light&quot;&gt;AppFuse Light&lt;/a&gt;. I&apos;m glad I did, because it took some effort to get jQuery and Bootstrap integrated, as well as to make it more secure. 
&lt;/p&gt;
&lt;p&gt;
The good news is AppFuse Light 2.2.1 is released and it&apos;s sitting out on the &lt;a href=&quot;http://search.maven.org/#search%7Cga%7C1%7Cappfuse-light&quot;&gt;Central Repository&lt;/a&gt;. This release is a refactoring of all  archetypes to be up-to-date with the AppFuse 2.2.1 release. This means Java 7 compatibility, Servlet 3, Bootstrap/jQuery integration, Tapestry 5.3.6 upgrade and security improvements. I integrated Bootstrap and jQuery using &lt;a href=&quot;http://www.webjars.org/documentation&quot;&gt;WebJars Servlet 3 support&lt;/a&gt; since it was simple and straightforward. 
&lt;/p&gt;
&lt;p&gt;
You can create projects using AppFuse&apos;s light archetypes using a command such as the following:
&lt;/p&gt;
&lt;pre class=&quot;brush: shell&quot;&gt;
mvn archetype:generate -B -DarchetypeGroupId=org.appfuse.archetypes 
  -DarchetypeArtifactId=appfuse-light-spring-freemarker-archetype -DarchetypeVersion=2.2.1 
  -DgroupId=com.mycompany -DartifactId=myproject 
&lt;/pre&gt;
&lt;p&gt;
The list of archetypes is as follows:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;appfuse-light-jsf-archetype&lt;/li&gt;
&lt;li&gt;appfuse-light-spring-archetype&lt;/li&gt;
&lt;li&gt;appfuse-light-spring-freemarker-archetype&lt;/li&gt;
&lt;li&gt;appfuse-light-spring-security-archetype&lt;/li&gt;
&lt;li&gt;appfuse-light-stripes-archetype&lt;/li&gt;
&lt;li&gt;appfuse-light-struts-archetype&lt;/li&gt;
&lt;li&gt;appfuse-light-tapestry-archetype&lt;/li&gt;
&lt;li&gt;appfuse-light-wicket-archetype&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+QuickStart&quot;&gt;QuickStart Guide&lt;/a&gt; will help you get setup and demos are available at the following links:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://demo2.appfuse.org/appfuse-light-jsf&quot;&gt;JSF 2 + Hibernate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://demo2.appfuse.org/appfuse-light-spring&quot;&gt;Spring MVC 3 + Hibernate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://demo2.appfuse.org/appfuse-light-spring-freemarker&quot;&gt;Spring MVC 3 + FreeMarker + Hibernate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://demo2.appfuse.org/appfuse-light-spring-security&quot;&gt;Spring MVC 3 + Spring Security + Hibernate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://demo2.appfuse.org/appfuse-light-stripes&quot;&gt;Stripes + Hibernate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://demo2.appfuse.org/appfuse-light-struts&quot;&gt;Struts 2 + Hibernate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://demo2.appfuse.org/appfuse-light-tapestry&quot;&gt;Tapestry 5 + Hibernate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://demo2.appfuse.org/appfuse-light-wicket&quot;&gt;Wicket + Hibernate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have questions about AppFuse, we invite you to ask them on the &lt;a href=&quot;http://appfuse.org/display/APF/Mailing+Lists&quot;&gt;users mailing list&lt;/a&gt; or tweet using #appfuse. &lt;/p&gt;
&lt;p&gt;
For those enjoying &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt; in your apps, I encourage you to check out &lt;a href=&quot;https://wrapbootstrap.com/&quot;&gt;{wrap}bootstrap&lt;/a&gt; and &lt;a href=&quot;http://bootswatch.com/&quot;&gt;Bootswatch&lt;/a&gt;.&lt;/p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_2_2_1_released</guid>
    <title>AppFuse 2.2.1 Released!</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_2_2_1_released</link>
        <pubDate>Tue, 11 Dec 2012 15:21:44 -0700</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>security</category>
    <category>appfuse</category>
    <category>java</category>
    <category>hibernate</category>
    <category>spring</category>
            <description>&lt;a href=&quot;http://appfuse.org&quot;&gt;&lt;img src=&quot;//static.appfuse.org/images/appfuse-icon.gif&quot; class=&quot;picture&quot; style=&quot;border: 0&quot;&gt;&lt;/a&gt;
The AppFuse Team is pleased to announce the release of AppFuse 2.2.1. This release includes upgrades to all dependencies to bring them up-to-date with their latest releases. Most notable are Hibernate 4, Struts 2.3.7, Apache CXF 2.7.0 and Spring Security 3.1.3. In addition, we&apos;ve integrated HTML5, Twitter Bootstrap, jQuery and replaced Compass with Hibernate Search. Last but not least, we&apos;ve added full support for Java 7 and integrated many &lt;a href=&quot;http://raibledesigns.com/rd/entry/java_web_application_security_part4&quot;&gt;security improvements&lt;/a&gt;. For more details on specific changes see the &lt;a href=&quot;http://appfuse.org/display/APF/Release+Notes+2.2.1&quot;&gt;release notes&lt;/a&gt;.&lt;/p&gt;

&lt;p class=&quot;quote&quot;&gt;&lt;strong&gt;What is AppFuse?&lt;/strong&gt;&lt;br/&gt;AppFuse is a full-stack framework for building web applications on the JVM. It was originally developed to eliminate the ramp-up time when building new web applications. Over the years, it has matured into a very testable and secure system for creating Java-based webapps.
&lt;/p&gt;

&lt;p&gt;Demos for this release can be viewed at &lt;a href=&quot;http://demo.appfuse.org/&quot;&gt;http://demo.appfuse.org&lt;/a&gt;. Please see the &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+QuickStart&quot; style=&quot;font-weight: bold&quot;&gt;QuickStart Guide&lt;/a&gt; to get started with this release. &lt;/p&gt;

&lt;p&gt;A number of blog posts were written about features that went into this release while it was being developed:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/improving_appfuse_s_pagespeed_with&quot;&gt;Improving AppFuse&apos;s PageSpeed with Apache&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_news_liquibase_and_wro4j&quot;&gt;New Liquibase and wro4j Tutorials from J. Garc&#237;a&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_news_github_hibernate_search&quot;&gt;AppFuse News: GitHub, Hibernate Search and The Future&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/refreshing_appfuse_s_ui_with&quot;&gt;Refreshing AppFuse&apos;s UI with Twitter Bootstrap&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/upgrading_appfuse_to_spring_security&quot;&gt;Upgrading AppFuse to Spring Security 3.1 and Spring 3.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/integrating_oauth_with_appfuse_and&quot;&gt;Integrating OAuth with AppFuse and its REST API&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;If you have questions about AppFuse, please read the &lt;a href=&quot;http://appfuse.org/display/APF/FAQ&quot;&gt;FAQ&lt;/a&gt; or join the &lt;a href=&quot;http://appfuse.org/display/APF/Mailing+Lists&quot;&gt;mailing list&lt;/a&gt;. If you find any issues, please &lt;a href=&quot;http://appfuse.547863.n4.nabble.com/ANN-AppFuse-2-2-1-Released-td4656067.html&quot;&gt;report them on the users mailing list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to everyone for their help contributing patches, writing documentation and participating on the mailing lists.&lt;/p&gt;
&lt;p style=&quot;border-top: 1px dotted silver; padding-top: 5px; color: #666&quot;&gt;We greatly appreciate the help from &lt;a href=&quot;http://appfuse.org/display/APF/Sponsors&quot; title=&quot;Sponsors&quot; style=&quot;color: #666&quot;&gt;our sponsors&lt;/a&gt;, particularly &lt;a href=&quot;http://www.atlassian.com/c/NPOS/10160&quot; style=&quot;color: #666&quot;&gt;Atlassian&lt;/a&gt;, &lt;a href=&quot;http://contegix.com&quot; style=&quot;color: #666&quot;&gt;Contegix&lt;/a&gt; and &lt;a href=&quot;http://www.jetbrains.com&quot; style=&quot;color: #666&quot;&gt;JetBrains&lt;/a&gt;. We highly recommend using the new &lt;a href=&quot;http://blogs.jetbrains.com/idea/2012/12/intellij-idea-12-is-available-for-download/&quot;&gt;IntelliJ IDEA 12&lt;/a&gt; for developing web applications.&lt;/p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/deploying_java_and_play_framework</guid>
    <title>Deploying Java and Play Framework Apps to the Cloud with James Ward</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/deploying_java_and_play_framework</link>
        <pubDate>Fri, 18 Nov 2011 08:14:45 -0700</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>playframework</category>
    <category>sbt</category>
    <category>java</category>
    <category>springroo</category>
    <category>scala</category>
    <category>heroku</category>
    <category>devoxx2011</category>
    <category>jamesward</category>
    <category>devoxx</category>
            <description>Yesterday, I attended &lt;a href=&quot;http://www.jamesward.com/&quot;&gt;James Ward&lt;/a&gt;&apos;s presentation on &lt;a href=&quot;http://www.devoxx.com/pages/viewpage.action?pageId=5015973&quot;&gt;Deploying Java &amp;amp; Play Framework Apps to the Cloud&lt;/a&gt; at Devoxx. I arrived a bit late, but still managed to get there in time to see a lot of demos and learn more about &lt;a href=&quot;http://heroku.com&quot;&gt;Heroku&lt;/a&gt;. Below are my notes from James&apos;s talk.
&lt;/p&gt;
&lt;p&gt;When I arrived, James was doing a demo using &lt;a href=&quot;http://www.springsource.org/spring-roo&quot;&gt;Spring Roo&lt;/a&gt;. He was using Roo&apos;s Petclinic sample app and showed us how you could use Git to create a local repository of the new project and install Heroku&apos;s command line tool. From there, he ran the following command to create a new application on Heroku.
&lt;/p&gt;
&lt;pre&gt;heroku create -s cedar&lt;/pre&gt;
&lt;p&gt;The &lt;a href=&quot;http://devcenter.heroku.com/articles/cedar&quot;&gt;Cedar Stack&lt;/a&gt; is what supports Java, Scala and Play Framework. It&apos;s the 3rd generation stack for Heroku. The command above created two endpoints, one for HTTP and one for Git. It picks from a list of randomly generated names, which all seem to have some humor in them. James ended up with &quot;electric-sword-8877&quot; for this demo.&lt;/p&gt;
&lt;p&gt;From there, he ran &lt;code&gt;git push heroku master&lt;/code&gt; to deploy the project to Heroku. Unfortunately, this resulted in a login error and there was an akward moment where we all thought the Demo Gods were angry. However, James was able to resolve this by using Heroku&apos;s sharing feature with the following command.
&lt;/p&gt;
&lt;pre&gt;
heroku sharing:add jw@heroku.com
&lt;/pre&gt;
&lt;p&gt;For Java projects, Heroku looks for a pom.xml file in the root directory and runs a Maven build on project. All the dependencies get downloaded on the cloud rather than put them into a WAR and requiring you to upload a large WAR file. You don&apos;t have to upload your source code to Heroku; James did it for the sake of the demo because it was faster.
&lt;/p&gt;
&lt;p&gt;After the build finishes, it creates a &lt;em&gt;slug&lt;/em&gt; file. This file contains everything Heroku needs to run your application. 
&lt;p&gt;Next, James showed a demo of the running application and added a new Pet through its UI. Then he scaled it to two servers using the following command:
&lt;/p&gt;
&lt;pre&gt;
heroku scale web=2
&lt;/pre&gt;
&lt;p&gt;
He proved this was working by running &lt;code&gt;heroku ps&lt;/code&gt;, which showed there were two running processes. He showed the app again, but noted that the record he added was missing. This is because when it started up a new dyno, Hibernate created the schema again and deleted all records. To fix, James changed Hibernate to only update the schema instead of create a new one. If you&apos;re a Hibernate user, you know this is as simple as changing:
&lt;/p&gt;
&lt;pre&gt;
hibernate.hbm2ddl.auto=create
&lt;/pre&gt;
&lt;p&gt;to:
&lt;pre&gt;
hibernate.hbm2ddl.auto=update
&lt;/pre&gt;
&lt;p&gt;After committing this change, James redeployed using Git.
&lt;/p&gt;
&lt;pre&gt;
git push heroku master
&lt;/pre&gt;
&lt;p&gt;The slug file got built again and Heroku deployed the new slug onto both dynos, automatically load balancing the app across two servers. James then ran &lt;code&gt;heroku logs&lt;/code&gt; to see the logs of his dynos and prove that a request to his app&apos;s HTTP endpoint made requests to both dynos. The logging is powered by &lt;a href=&quot;https://github.com/heroku/logplex&quot;&gt;Logplex&lt;/a&gt; and you can read about how it works in the article &lt;a href=&quot;http://blog.heroku.com/archives/2010/12/13/logging/&quot;&gt;Heroku Gets Sweet Logging&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;James mentioned that Roo has a Heroku plugin, but after watching his talk and searching a bit on the internet, it seems it&apos;s just the jetty-runner setup as described in &lt;a href=&quot;http://devcenter.heroku.com/articles/spring-mvc-hibernate&quot;&gt;Getting Started with Spring MVC Hibernate on Heroku/Cedar&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
What about autoscaling? There are some 3rd party tools that do this. Heroku&apos;s Management infrastructure has APIs that these tools talk too. Heroku hasn&apos;t built autoscaling into the platform because they don&apos;t know where the bottlenecks are in your application.
&lt;/p&gt;
&lt;p&gt;
Heroku = Polyglot + PaaS + Cloud Components. It supports Ruby, node.js, Java, Clojure, Play and Scala and they&apos;re working on native Grails and Gradle support. There&apos;s currently 534,374 apps running on Heroku.
&lt;/p&gt;
&lt;p&gt;
Heroku is a cloud application platform and there&apos;s 5 different components. 
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Instant deployment&lt;/li&gt;
&lt;li&gt;HTTP Routing / Load Balancing&lt;/li&gt;
&lt;li&gt;Elastic Polyglot Runtime&lt;/li&gt;
&lt;li&gt;Management &amp;amp; Logging&lt;/li&gt;
&lt;li&gt;Component as a Service Ecosystem&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
For instant deployment, it&apos;s a pretty simple process:
&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;You add files to a git repo&lt;/li&gt;
&lt;li&gt;You provision the app on Heroku (heroku create)&lt;/li&gt;
&lt;li&gt;You upload the files to Heroku (git push heroku master)&lt;/li&gt;
&lt;li&gt;Heroku runs the build and assembles a &quot;slug&quot; file&lt;/li&gt;
&lt;li&gt;Heroku starts a &quot;dyno&quot;&lt;/li&gt;
&lt;li&gt;Heroku copies the &quot;slug&quot; to the &quot;dyno&quot;&lt;/li&gt;
&lt;li&gt;Heroku starts the web application&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most apps will contain a &lt;em&gt;Procfile&lt;/em&gt; that contains information about how to run the web process. For Spring Roo, it has:
&lt;/p&gt;
&lt;pre&gt;
web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war
&lt;/pre&gt;
&lt;p&gt;So how does Heroku decide what application server to use? It doesn&apos;t, you do. You need to get your application server into the slug file. 
The easiest way to do this is to specify your application server as a dependency in your pom.xml. In the Roo example, James uses the maven-dependency-plugin to get the jetty-runner dependency and copy it to the target directory. On Heroku, you bring your application server with you.
&lt;/p&gt;
&lt;p&gt;Heroku gives you 750 free dyno hours per app, per month. For developers, it&apos;s very easy to get started and use. Once you extend past one dyno, it&apos;s
  $.05 per dyno hour, which works out to around $30/month.

It&apos;s only when you want to scale beyond one dyno where you get charged by Heroku, no matter how much data you transfer.

&lt;a href=&quot;http://www.scalatest.org/&quot;&gt;Scalatest&lt;/a&gt; is running on Heroku. It has one dyno and is doing fine with that. Bill Venners doesn&apos;t have to pay anything for it.
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://java.herokuapp.com&quot;&gt;java.herokuapp.com&lt;/a&gt; is a site James created that allows you to clone example apps and get started quickly with Heroku&apos;s Cedar Stack.&lt;/p&gt;
&lt;p&gt;
For 
HTTP Routing, 
Heroku uses an Erlang-based routing system to route all the HTTP requests across your dynos. Heroku doesn&apos;t support sticky sessions. Distributed session management does not work well, because it does not scale well. Heroku recommends you use a stateless web architecture or move your state into something like &lt;a href=&quot;http://memcached.org/&quot;&gt;memcached&lt;/a&gt;. Jetty has (in the latest version) the ability to automatically serialize your session into a Mongo system. This works fine on Heroku. The problem with this is if you have 2 dynos running, each request can hit a different dyno and get different session state. Hence the recommendation for an external storage mechanism that can synchronize between dynos.
&lt;/p&gt;
You can also run non-web applications on Heroku. You can have one web process, but as many non-web processes as you want.
&lt;/p&gt;
&lt;p&gt;Heroku has native support for the &lt;a href=&quot;http://www.playframework.org/&quot;&gt;Play framework&lt;/a&gt;. To detect Play applications, it look for a &lt;em&gt;conf/application.conf&lt;/em&gt; file. You don&apos;t need to have a Procfile in your root directory because Heroku knows how to start a Play application.
&lt;/p&gt;
&lt;p&gt;At this point, James created a new Play application, created a new Heroku app (he got &quot;young-night-7104&quot; this time) and pushed it to Heroku. He created a simple model object, a controller to allow adding new data and then wrote some jQuery to show new records via Ajax and JSON. He also showed how to configure the application to talk to Heroku&apos;s PostgreSQL database using the DATABASE_URL environment variable. He explained how you can use the &lt;code&gt;heroku config&lt;/code&gt; command to see your environment variables.
&lt;/p&gt;
&lt;p&gt;
The reason they use environment variables is so Heroku can update DATABASE_URL (and other variables) without having to call up all their customers and have them change them in their source code.
&lt;/p&gt;
&lt;p&gt;
Play on Heroku supports Scala if you create your app with Scala. Play 2.0 uses Scala, Akka and SBT. Heroku added support for SBT a couple month ago, so everything will work just fine.
&lt;/p&gt;
&lt;p&gt;Heroku also supports Scala, detecting it by looking for the &lt;code&gt;build.sbt&lt;/code&gt; file in the root directory. Heroku supports SBT 0.11.0 and it builds the &apos;stage&apos; task.
It currently does not support Lift because Lift uses an older version of SBT and because it&apos;s a very stateful framework that would require sticky sessions. Use Play, &lt;a href=&quot;https://github.com/jdegoes/blueeyes&quot;&gt;BlueEyes&lt;/a&gt; or &lt;a href=&quot;http://www.scalatra.org/&quot;&gt;Scalatra&lt;/a&gt; if you want Scala on Heroku.
&lt;/p&gt;
&lt;p&gt;Heroku has &lt;a href=&quot;http://addons.heroku.com&quot;&gt;addons&lt;/a&gt; for adding functionality to your application, including Custom DNS, HTTPS, Amazon RDS, NoSQL and many more. They&apos;re also working on making their add-on and management APIs available via Java, so you&apos;ll (hopefully) be able to use them from your IDE in the future.
&lt;/p&gt;
&lt;p&gt;From there, James showed us how Heroku keeps slug files around so you can do rollbacks with &lt;code&gt;heroku rollback&lt;/code&gt;. He also showed how you can use:
&lt;/p&gt;
&lt;pre&gt;heroku run &quot;your bash command&quot;&lt;/pre&gt;
to run any Bash command on the cloud.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br&gt;
I attended James&apos;s talk because he&apos;s a good friend, but also because I&apos;ve been using Heroku to host &lt;a href=&quot;http://raibledesigns.com/rd/entry/phonegap_to_the_rescue&quot;&gt;my latest adventures with Play, Scala, CoffeeScript and Jade&lt;/a&gt;. I&apos;m glad I attended because I learned some good tips and tricks and more about how Heroku works. 
&lt;/p&gt;
&lt;p&gt;Heroku seems like a great development tool to me. In my experience, it&apos;s been really nice to have instant deployments using Git. In fact, I&apos;ve created a &apos;push&apos; alias so I can push to my project&apos;s repo and heroku at the same time.
&lt;/p&gt;
&lt;pre&gt;
alias push=&apos;git push origin master &amp;&amp; git push heroku master&apos;
&lt;/pre&gt;
&lt;p&gt;I&apos;d like to see more organizations embrace something like Heroku for developers. It&apos;d be great if everyone had their own sandbox that business owners and product managers could see. I can&apos;t help but think this would be awesome for demos, prototyping, etc.
&lt;/p&gt;
&lt;p&gt;
There were some other talks I wanted to attend at the same time, particularly Martin Odersky&apos;s &lt;a href=&quot;http://www.devoxx.com/pages/viewpage.action?pageId=5015952&quot;&gt;What&apos;s in store for Scala?&lt;/a&gt; and &lt;a href=&quot;http://www.devoxx.com/display/DV11/WWW++World+Wide+Wait++A+Performance+Comparison+of+Java+Web+Frameworks&quot;&gt;WWW: World Wide Wait? A Performance Comparison of Java Web Frameworks&lt;/a&gt;. The WWW talk has &lt;a href=&quot;http://prezi.com/dr3on1qcajzw/www-world-wide-wait-devoxx-edition/&quot;&gt;posted their presentation&lt;/a&gt; but I&apos;m sure it&apos;d be more fun to watch. 
&lt;/p&gt;
&lt;p&gt;
It&apos;s pretty awesome that all the talks from Devoxx 2011 will be up on &lt;a href=&quot;http://www.parleys.com/&quot;&gt;Parleys.com&lt;/a&gt; soon.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; James has &lt;a href=&quot;http://www.jamesward.com/2011/11/29/heroku-preso-from-devoxx-2011&quot;&gt;posted his slides&lt;/a&gt; from this talk.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_2_1_released</guid>
    <title>AppFuse 2.1 Released!</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_2_1_released</link>
        <pubDate>Mon, 4 Apr 2011 09:38:05 -0600</pubDate>
    <category>Java</category>
    <category>myfaces</category>
    <category>javaee</category>
    <category>ibatis</category>
    <category>appfuse</category>
    <category>springmvc</category>
    <category>tapestry5</category>
    <category>appfuse-light</category>
    <category>jsf2</category>
    <category>hibernate</category>
    <category>jpa</category>
    <category>spring</category>
    <category>struts2</category>
    <category>java</category>
    <category>maven</category>
            <description>&lt;a href=&quot;http://appfuse.org&quot;&gt;&lt;img src=&quot;//static.appfuse.org/images/appfuse-icon.gif&quot; class=&quot;picture&quot; style=&quot;border: 0&quot;&gt;&lt;/a&gt;
The AppFuse Team is pleased to announce the release of AppFuse 2.1. This release includes upgrades to all dependencies to bring them up-to-date with their latest releases. Most notable are JPA 2, JSF 2, Tapestry 5 and Spring 3. In addition, we&apos;ve migrated from XFire to CXF and enabled REST for web services. There&apos;s even a new &lt;b&gt;appfuse-ws&lt;/b&gt; archetype that leverages &lt;a href=&quot;http://enunciate.codehaus.org&quot;&gt;Enunciate&lt;/a&gt; to generate web service endpoints, documentation and downloadable clients. This release fixes many issues with archetypes, improving startup time and allowing jetty:run to be used for quick turnaround while developing. For more details on specific changes see the &lt;a href=&quot;http://appfuse.org/display/APF/Release+Notes+2.1.0&quot; title=&quot;Release Notes 2.1.0&quot;&gt;release notes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is AppFuse?&lt;/strong&gt;&lt;br/&gt;AppFuse is an open source project and application that uses open source frameworks to help you develop Web applications with Java quickly and efficiently. It was originally developed to eliminate the ramp-up time when building new web applications. At its core, AppFuse is a project skeleton, similar to the one that&apos;s created by your IDE when you click through a wizard to create a new web project. If you use &lt;a href=&quot;http://appfuse.org/display/APF/Using+JRebel+with+IntelliJ+IDEA&quot;&gt;JRebel with IntelliJ&lt;/a&gt;, you can achieve zero-turnaround in your project and develop features without restarting the server.
&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Release Details&lt;/b&gt;&lt;br/&gt;
&lt;a href=&quot;http://static.appfuse.org/archetypes.html&quot;&gt;Archetypes&lt;/a&gt; now include all the source for the web modules so using jetty:run and your IDE will work much smoother now. The backend is still embedded in JARs, enabling you to choose with persistence framework (Hibernate, iBATIS or JPA) you&apos;d like to use. If you want to modify the source for that, &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+Core+Classes&quot;&gt;add the core classes to your project&lt;/a&gt; or run &quot;appfuse:full-source&quot;. &lt;/p&gt;

&lt;p&gt;AppFuse comes in a number of different flavors. It offers &quot;light&quot;, &quot;basic&quot; and &quot;modular&quot; and archetypes. Light archetypes use an embedded H2 database and contain a simple CRUD example. Light archetypes allow code generation and full-source features, but do not currently support Stripes or Wicket. Basic archetypes have web services using CXF, authentication from Spring Security and features including signup, login, file upload and CSS theming. Modular archetypes are similar to basic archetypes, except they have multiple modules which allows you to separate your services from your web project.&lt;/p&gt;

&lt;p&gt;AppFuse provides archetypes for JSF, Spring MVC, Struts 2 and Tapestry 5. The light archetypes are available for these frameworks, as well as for Spring MVC + FreeMarker, Stripes and Wicket. You can see demos of these archetypes at &lt;a href=&quot;http://demo.appfuse.org&quot;&gt;http://demo.appfuse.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For information on creating a new project, please see the &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+QuickStart&quot;&gt;QuickStart Guide&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If you have questions about AppFuse, please read the &lt;a href=&quot;http://appfuse.org/display/APF/FAQ&quot;&gt;FAQ&lt;/a&gt; or join the &lt;a href=&quot;http://appfuse.org/display/APF/Mailing+Lists&quot;&gt;user mailing list&lt;/a&gt;. If you find any issues, please report them on the mailing list or &lt;a href=&quot;http://issues.appfuse.org/secure/CreateIssue%21default.jspa&quot;&gt;create an issue in JIRA&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to everyone for their help contributing patches, writing documentation and participating on the mailing lists.&lt;/p&gt;
&lt;p style=&quot;border-top: 1px dotted silver; padding-top: 5px; color: #666&quot;&gt;We greatly appreciate the help from &lt;a href=&quot;http://appfuse.org/display/APF/Sponsors&quot; title=&quot;Sponsors&quot; style=&quot;color: #666&quot;&gt;our sponsors&lt;/a&gt;, particularly &lt;a href=&quot;http://www.atlassian.com/c/NPOS/10160&quot; style=&quot;color: #666&quot;&gt;Atlassian&lt;/a&gt;, &lt;a href=&quot;http://contegix.com&quot; style=&quot;color: #666&quot;&gt;Contegix&lt;/a&gt; and &lt;a href=&quot;http://www.jetbrains.com&quot; style=&quot;color: #666&quot;&gt;JetBrains&lt;/a&gt;. Atlassian and Contegix are especially awesome: &lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_now_powered_by_contegix&quot; style=&quot;color: #666&quot;&gt;Atlassian has donated licenses to all its products and Contegix has donated an entire server&lt;/a&gt; to the AppFuse project.&lt;/p&gt;&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/integration_testing_with_http_https</guid>
    <title>Integration Testing with HTTP, HTTPS and Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/integration_testing_with_http_https</link>
        <pubDate>Fri, 11 Feb 2011 15:54:16 -0700</pubDate>
    <category>Java</category>
    <category>cargo</category>
    <category>jetty</category>
    <category>overstock.com</category>
    <category>ssl</category>
    <category>http</category>
    <category>tomcat</category>
    <category>maven</category>
    <category>https</category>
            <description>Earlier this week, I was tasked with getting automated integration tests working in my project at &lt;a href=&quot;http://overstock.com&quot;&gt;Overstock.com&lt;/a&gt;. By &lt;em&gt;automated&lt;/em&gt;, I mean that ability to run &quot;mvn install&quot; and have the following process cycled through: 
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Start a container&lt;/li&gt;
&lt;li&gt;Deploy the application&lt;/li&gt;
&lt;li&gt;Run all integration tests&lt;/li&gt;
&lt;li&gt;Stop the container&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since it makes sense for integration tests to run in Maven&apos;s &lt;em&gt;integration-test&lt;/em&gt; phase, I first configured the maven-surefire-plugin to skip tests in the &lt;em&gt;test&lt;/em&gt; phase and execute them in the &lt;em&gt;integration-test&lt;/em&gt; phase. I used the &amp;lt;id&gt;&lt;strong&gt;default-&lt;/strong&gt;&lt;em&gt;phase&lt;/em&gt;&amp;lt;/id&gt; syntax to override the plugins&apos; usual behavior.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
  &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;executions&amp;gt;
    &amp;lt;execution&amp;gt;
      &amp;lt;id&amp;gt;default-test&amp;lt;/id&amp;gt;
      &amp;lt;configuration&amp;gt;
        &amp;lt;excludes&amp;gt;
          &amp;lt;exclude&amp;gt;**/*Test*.java&amp;lt;/exclude&amp;gt;
        &amp;lt;/excludes&amp;gt;
      &amp;lt;/configuration&amp;gt;
    &amp;lt;/execution&amp;gt;
    &amp;lt;execution&amp;gt;
      &amp;lt;id&amp;gt;default-integration-test&amp;lt;/id&amp;gt;
      &amp;lt;phase&amp;gt;integration-test&amp;lt;/phase&amp;gt;
      &amp;lt;goals&amp;gt;
        &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;
      &amp;lt;/goals&amp;gt;
      &amp;lt;configuration&amp;gt;
        &amp;lt;includes&amp;gt;
          &amp;lt;include&amp;gt;**/*Test.java&amp;lt;/include&amp;gt;
        &amp;lt;/includes&amp;gt;
        &amp;lt;excludes&amp;gt;
          &amp;lt;exclude&amp;gt;none&amp;lt;/exclude&amp;gt;
          &amp;lt;exclude&amp;gt;**/TestCase.java&amp;lt;/exclude&amp;gt;
        &amp;lt;/excludes&amp;gt;
      &amp;lt;/configuration&amp;gt;
    &amp;lt;/execution&amp;gt;
  &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;After I had this working, I moved onto getting the container started and stopped properly. In the past, I&apos;ve &lt;a href=&quot;http://raibledesigns.com/rd/entry/integrating_selenium_with_maven_2&quot;&gt;done this&lt;/a&gt; using &lt;a href=&quot;http://cargo.codehaus.org&quot;&gt;Cargo&lt;/a&gt; and it&apos;s always worked well for me. Apart from the usual setup I use in AppFuse archetypes (&lt;a href=&quot;http://source.appfuse.org/browse/appfuse/trunk/archetypes/appfuse-basic-struts/src/pom.xml?r=HEAD#l496&quot;&gt;example pom.xml&lt;/a&gt;), I added a couple additional items:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Added &amp;lt;timeout&gt;180000&amp;lt;/timeout&gt; so the container would wait up to 3 minutes for the WAR to deploy.&lt;/li&gt;
&lt;li&gt;In configuration/properties, specified &amp;lt;context.path&gt;ROOT&amp;lt;/context.path&gt; so the app would deploy at the / context path.&lt;/li&gt;
&lt;li&gt;In configuration/properties, specified &amp;lt;cargo.protocol&gt;https&amp;lt;/cargo.protocol&gt; since many existing unit tests made requests to secure resources.
&lt;/ul&gt;
&lt;p&gt;I started by using Cargo with Tomcat and had to &lt;a href=&quot;http://tomcat.apache.org/tomcat-6.0-doc/ssl-howto.html&quot;&gt;create certificate keystore&lt;/a&gt; in order to get Tomcat to start with SSL enabled. After getting it to start, I found the tests failed with the following errors in the logs:
&lt;/p&gt;
&lt;pre&gt;
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: 
unable to find valid certification path to requested target
	at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
	at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1649)
&lt;/pre&gt;
&lt;p&gt;Co-workers told me this was easily solved by &lt;a href=&quot;http://blogs.sun.com/gc/entry/unable_to_find_valid_certification&quot;&gt;adding my &apos;untrusted&apos; cert to my JVM keystore&lt;/a&gt;. Once all this was working, I thought I was good to go, but found that some tests were still failing. The failures turned out to be because they were talking to http and https was the only protocol enabled. After doing some research, I discovered that Cargo &lt;a href=&quot;http://jira.codehaus.org/browse/CARGO-574&quot;&gt;doesn&apos;t support starting on both http and https ports&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So back to the drawing board I went. I ended up turning to the &lt;a href=&quot;http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin&quot;&gt;maven-jetty-plugin&lt;/a&gt; and the &lt;a href=&quot;http://mojo.codehaus.org/tomcat-maven-plugin/&quot;&gt;tomcat-maven-plugin&lt;/a&gt; to get the functionality I was looking for. I also automated the certificate keystore generation using the &lt;a href=&quot;http://mrhaki.blogspot.com/2009/05/configure-maven-jetty-plugin-for-ssl.html&quot;&gt;keytool-maven-plugin&lt;/a&gt;. Below is the extremely-verbose 95-line profiles section of my pom.xml that allows either container to be used.
&lt;/p&gt;
&lt;p style=&quot;margin-left: 20px&quot;&gt;&lt;em&gt;Sidenote: I wonder how this same setup would look using &lt;a href=&quot;http://www.gradle.org&quot;&gt;Gradle&lt;/a&gt;?&lt;/em&gt;
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;profiles&amp;gt;
  &amp;lt;profile&amp;gt;
    &amp;lt;id&amp;gt;jetty&amp;lt;/id&amp;gt;
    &amp;lt;activation&amp;gt;
      &amp;lt;activeByDefault&amp;gt;true&amp;lt;/activeByDefault&amp;gt;
    &amp;lt;/activation&amp;gt;
    &amp;lt;build&amp;gt;
      &amp;lt;plugins&amp;gt;
        &amp;lt;plugin&amp;gt;
          &amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;
          &amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;
          &amp;lt;version&amp;gt;6.1.26&amp;lt;/version&amp;gt;
          &amp;lt;configuration&amp;gt;
            &amp;lt;contextPath&amp;gt;/&amp;lt;/contextPath&amp;gt;
            &amp;lt;connectors&amp;gt;
              &amp;lt;connector implementation=&quot;org.mortbay.jetty.nio.SelectChannelConnector&quot;&amp;gt;
                &amp;lt;!-- forwarded == true interprets x-forwarded-* headers --&amp;gt;
                &amp;lt;!-- http://docs.codehaus.org/display/JETTY/Configuring+mod_proxy --&amp;gt;
                &amp;lt;forwarded&amp;gt;true&amp;lt;/forwarded&amp;gt;
                &amp;lt;port&amp;gt;8080&amp;lt;/port&amp;gt;
                &amp;lt;maxIdleTime&amp;gt;60000&amp;lt;/maxIdleTime&amp;gt;
              &amp;lt;/connector&amp;gt;
              &amp;lt;connector implementation=&quot;org.mortbay.jetty.security.SslSocketConnector&quot;&amp;gt;
                &amp;lt;forwarded&amp;gt;true&amp;lt;/forwarded&amp;gt;
                &amp;lt;port&amp;gt;8443&amp;lt;/port&amp;gt;
                &amp;lt;maxIdleTime&amp;gt;60000&amp;lt;/maxIdleTime&amp;gt;
                &amp;lt;keystore&amp;gt;${project.build.directory}/ssl.keystore&amp;lt;/keystore&amp;gt;
                &amp;lt;password&amp;gt;overstock&amp;lt;/password&amp;gt;
                &amp;lt;keyPassword&amp;gt;overstock&amp;lt;/keyPassword&amp;gt;
              &amp;lt;/connector&amp;gt;
            &amp;lt;/connectors&amp;gt;
            &amp;lt;stopKey&amp;gt;overstock&amp;lt;/stopKey&amp;gt;
            &amp;lt;stopPort&amp;gt;9999&amp;lt;/stopPort&amp;gt;
          &amp;lt;/configuration&amp;gt;
          &amp;lt;executions&amp;gt;
            &amp;lt;execution&amp;gt;
              &amp;lt;id&amp;gt;start-jetty&amp;lt;/id&amp;gt;
              &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;
              &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;run-war&amp;lt;/goal&amp;gt;
              &amp;lt;/goals&amp;gt;
              &amp;lt;configuration&amp;gt;
                &amp;lt;daemon&amp;gt;true&amp;lt;/daemon&amp;gt;
              &amp;lt;/configuration&amp;gt;
            &amp;lt;/execution&amp;gt;
            &amp;lt;execution&amp;gt;
              &amp;lt;id&amp;gt;stop-jetty&amp;lt;/id&amp;gt;
              &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;
              &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;stop&amp;lt;/goal&amp;gt;
              &amp;lt;/goals&amp;gt;
            &amp;lt;/execution&amp;gt;
          &amp;lt;/executions&amp;gt;
        &amp;lt;/plugin&amp;gt;
      &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
  &amp;lt;/profile&amp;gt;
  &amp;lt;profile&amp;gt;
    &amp;lt;id&amp;gt;tomcat&amp;lt;/id&amp;gt;
    &amp;lt;build&amp;gt;
      &amp;lt;plugins&amp;gt;
        &amp;lt;plugin&amp;gt;
          &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
          &amp;lt;artifactId&amp;gt;tomcat-maven-plugin&amp;lt;/artifactId&amp;gt;
          &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
          &amp;lt;configuration&amp;gt;
            &amp;lt;addContextWarDependencies&amp;gt;true&amp;lt;/addContextWarDependencies&amp;gt;
            &amp;lt;fork&amp;gt;true&amp;lt;/fork&amp;gt;
            &amp;lt;path&amp;gt;/&amp;lt;/path&amp;gt;
            &amp;lt;port&amp;gt;8080&amp;lt;/port&amp;gt;
            &amp;lt;httpsPort&amp;gt;8443&amp;lt;/httpsPort&amp;gt;
            &amp;lt;keystoreFile&amp;gt;${project.build.directory}/ssl.keystore&amp;lt;/keystoreFile&amp;gt;
            &amp;lt;keystorePass&amp;gt;overstock&amp;lt;/keystorePass&amp;gt;
          &amp;lt;/configuration&amp;gt;
          &amp;lt;executions&amp;gt;
            &amp;lt;execution&amp;gt;
              &amp;lt;id&amp;gt;start-tomcat&amp;lt;/id&amp;gt;
              &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;
              &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;run-war&amp;lt;/goal&amp;gt;
              &amp;lt;/goals&amp;gt;
            &amp;lt;/execution&amp;gt;
            &amp;lt;execution&amp;gt;
              &amp;lt;id&amp;gt;stop-tomcat&amp;lt;/id&amp;gt;
              &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;
              &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;shutdown&amp;lt;/goal&amp;gt;
              &amp;lt;/goals&amp;gt;
            &amp;lt;/execution&amp;gt;
          &amp;lt;/executions&amp;gt;
        &amp;lt;/plugin&amp;gt;
      &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
  &amp;lt;/profile&amp;gt;
&amp;lt;/profiles&amp;gt;
&lt;/pre&gt;
&lt;p&gt;With this setup in place, I was able to automate running our integration tests by simply typing &quot;mvn install&quot; (for Jetty) or &quot;mvn install -Ptomcat&quot; (for Tomcat). For running in Hudson, it&apos;s possible I&apos;ll have to further enhance things to randomize the port and pass that into tests as a system property. The &lt;a href=&quot;http://mojo.codehaus.org/build-helper-maven-plugin/&quot;&gt;build-helper-maven-plugin&lt;/a&gt; and its &lt;em&gt;reserve-network-port&lt;/em&gt; goal is a nice way to do this. Note: if you want to run more than one instance of Tomcat at a time, you might have to randomize the ajp and rmi ports to avoid collisions.
&lt;/p&gt;
&lt;p&gt;The final thing I encountered was our app didn&apos;t shutdown gracefully. Luckily, this was fixed in a newer version of our core framework and upgrading fixed the problem. Here&apos;s the explanation from an architect on the core framework team.&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
The hanging problem was caused by the way the framework internally
aggregated statistics related to database connection usage and page
response times.  The aggregation runs on a separate thread but not as a
daemon thread.  Previously, the aggregation threads weren&apos;t being
terminated on shutdown so the JVM would hang waiting for them to finish.
In the new frameworks, the aggregation threads are terminated on shutdown.
&lt;/p&gt;
&lt;p&gt;Hopefully this post helps you test your secure and unsecure applications at the same time. At the same time, I&apos;m hoping it motivates the Cargo developers to add simultaneous http and https support. &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;)&quot; title=&quot;;)&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; In the comments, Ron Piterman recommended I use the &lt;a href=&quot;http://maven.apache.org/plugins/maven-failsafe-plugin/&quot;&gt;Maven Failsafe Plugin&lt;/a&gt; because its designed to run integration tests while Surefire Plugin is for unit tests. I changed my configuration to the following and everything still passes. Thanks Ron!
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
  &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;2.7.2&amp;lt;/version&amp;gt;
  &amp;lt;configuration&amp;gt;
    &amp;lt;skipTests&amp;gt;true&amp;lt;/skipTests&amp;gt;
  &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&amp;lt;plugin&amp;gt;
  &amp;lt;artifactId&amp;gt;maven-failsafe-plugin&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;2.7.2&amp;lt;/version&amp;gt;
  &amp;lt;configuration&amp;gt;
    &amp;lt;includes&amp;gt;
      &amp;lt;include&amp;gt;**/*Test.java&amp;lt;/include&amp;gt;
    &amp;lt;/includes&amp;gt;
    &amp;lt;excludes&amp;gt;
      &amp;lt;exclude&amp;gt;**/TestCase.java&amp;lt;/exclude&amp;gt;
    &amp;lt;/excludes&amp;gt;
  &amp;lt;/configuration&amp;gt;
  &amp;lt;executions&amp;gt;
    &amp;lt;execution&amp;gt;
      &amp;lt;id&amp;gt;integration-test&amp;lt;/id&amp;gt;
      &amp;lt;phase&amp;gt;integration-test&amp;lt;/phase&amp;gt;
      &amp;lt;goals&amp;gt;
        &amp;lt;goal&amp;gt;integration-test&amp;lt;/goal&amp;gt;
      &amp;lt;/goals&amp;gt;
    &amp;lt;/execution&amp;gt;
    &amp;lt;execution&amp;gt;
      &amp;lt;id&amp;gt;verify&amp;lt;/id&amp;gt;
      &amp;lt;phase&amp;gt;verify&amp;lt;/phase&amp;gt;
      &amp;lt;goals&amp;gt;
        &amp;lt;goal&amp;gt;verify&amp;lt;/goal&amp;gt;
      &amp;lt;/goals&amp;gt;
    &amp;lt;/execution&amp;gt;
  &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Update 2:&lt;/strong&gt; In addition to application changes to solve hanging issues, I also had to change my Jetty Plugin configuration to use a different SSL connector implementation. This also required adding the jetty-sslengine dependency, which has been &lt;a href=&quot;http://stackoverflow.com/questions/2215550/mavens-jetty-plugin-ssl-configuration-issue&quot;&gt;renamed to jetty-ssl for Jetty 7&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;connector implementation=&quot;org.mortbay.jetty.security.SslSelectChannelConnector&quot;&amp;gt;
...
&amp;lt;dependencies&amp;gt;
  &amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jetty-sslengine&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;6.1.26&amp;lt;/version&amp;gt;
  &amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt;
&lt;/pre&gt;&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/making_code_generation_smarter_with</guid>
    <title>Making Code Generation Smarter with Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/making_code_generation_smarter_with</link>
        <pubDate>Fri, 21 Jan 2011 15:26:43 -0700</pubDate>
    <category>Java</category>
    <category>overstock.com</category>
    <category>maven</category>
    <category>jamon</category>
            <description>As you might&apos;ve read in my &lt;a href=&quot;http://raibledesigns.com/rd/entry/2010_a_year_in_review&quot;&gt;last entry&lt;/a&gt;, I recently started a new gig with &lt;a href=&quot;http://www.overstock.com&quot;&gt;Overstock.com&lt;/a&gt;. On my first day, I was quickly immersed into the development process by joining the Conversion Team. The Conversion Team is responsible for developing the checkout UI and handling payments from customers. I quickly discovered Overstock was mostly a Linux + Eclipse Shop and did my best to get my favorite &lt;a href=&quot;http://raibledesigns.com/rd/entry/using_jrebel_with_intellij_idea&quot;&gt;Mac + IntelliJ + JRebel&lt;/a&gt; installed and configured. Thanks to my new Team Lead, I was able to get everything up and running the first day, as well as checkin my first contribution: making &lt;em&gt;mvn jetty:run&lt;/em&gt; work so I didn&apos;t have to use my IDE to deploy to Tomcat.
&lt;/p&gt;
&lt;p&gt;In setting up my environment, I couldn&apos;t help but notice running &lt;em&gt;jetty:run&lt;/em&gt; took quite a while to run each time. Specifically, the build process took 45 seconds to start executing the Jetty plugin, then another 23 seconds to startup after that. The first suspicious thing I noticed was that the UI templates were being re-generated and compiled on each execution. The UI Templating Framework at Overstock is &lt;a href=&quot;http://www.jamon.org/&quot;&gt;Jamon&lt;/a&gt;, and is described as follows:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Jamon is a text template engine for Java, useful for generating dynamic HTML, XML, or any text-based content. In a typical Model-View-Controller architecture, Jamon clearly is aimed at the View (or presentation) layer.
&lt;br/&gt;&lt;br/&gt;
Because it is compiled to non-reflective Java code, and statically type-checked, Jamon is ideally suited to support refactoring of template-based UI applications. Using mock objects -like functionality, Jamon also facilitates unit testing of the controller and view. 
&lt;/p&gt;
&lt;p&gt;To generate .java files from .jamon templates, we use the Jamon Plugin for Maven. Remembering that the &lt;a href=&quot;http://maven.apache.org/plugins/maven-compiler-plugin/&quot;&gt;Maven Compiler Plugin&lt;/a&gt; has an incremental-compile feature, I turned to its source code to find out how to implement this in the Jamon plugin. I was pleasantly surprised to find the &lt;a href=&quot;http://plexus.codehaus.org/plexus-components/plexus-compiler/plexus-compiler-api/apidocs/org/codehaus/plexus/compiler/util/scan/StaleSourceScanner.html&quot;&gt;StaleSourceScanner&lt;/a&gt;. This class allows you to easily compare two files to see if the source needs to re-examined for generation or compilation.&lt;/p&gt;
&lt;p&gt;I noticed the Jamon Plugin had the following code to figure out which files it should generate into .java files:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
private List&amp;lt;File&amp;gt; accumulateSources(File p_templateSourceDir)
{
  final List&amp;lt;File&amp;gt; result = new ArrayList&amp;lt;File&amp;gt;();
  if (p_templateSourceDir == null)
  {
    return result;
  }
  for (File f : p_templateSourceDir.listFiles())
  {
    if (f.isDirectory())
    {
      result.addAll(accumulateSources(f));
    }
    else if (f.getName().toLowerCase(Locale.US).endsWith(&quot;.jamon&quot;))
    {
      String filePath = f.getPath();
       // FIXME !?
      String basePath = templateSourceDir().getAbsoluteFile().toString();
      result.add(new File(filePath.substring(basePath.length() + 1)));
    }
  }
  return result;
}
&lt;/pre&gt;
&lt;p&gt;I changed it to be smarter and only generate changed templates with the following code:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
private List&amp;lt;File&amp;gt; accumulateSources(File p_templateSourceDir) throws MojoExecutionException
{
  final List&amp;lt;File&amp;gt; result = new ArrayList&amp;lt;File&amp;gt;();
  if (p_templateSourceDir == null)
  {
    return result;
  }
  SourceInclusionScanner scanner = getSourceInclusionScanner( staleMillis );
  SourceMapping mapping = new SuffixMapping( &quot;.jamon&quot;, &quot;.java&quot;);

  scanner.addSourceMapping( mapping );

  final Set&amp;lt;File&amp;gt; staleFiles = new LinkedHashSet&amp;lt;File&amp;gt;();

  for (File f : p_templateSourceDir.listFiles())
  {
    if (!f.isDirectory())
    {
      continue;
    }

    try
    {
      staleFiles.addAll( scanner.getIncludedSources(f.getParentFile(), templateOutputDir()));
    }
    catch ( InclusionScanException e )
    {
      throw new MojoExecutionException(
        &quot;Error scanning source root: \&apos;&quot; + p_templateSourceDir.getPath()
          + &quot;\&apos; &quot; + &quot;for stale files to recompile.&quot;, e );
    }
  }

  // Trim root path from file paths
  for (File file : staleFiles) {
    String filePath = file.getPath();
    String basePath = templateSourceDir().getAbsoluteFile().toString();
    result.add(new File(filePath.substring(basePath.length() + 1)));
  }
}
&lt;/pre&gt;
&lt;p&gt;This method references a getSourceInclusionScanner() method, which is implemented as follows:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
protected SourceInclusionScanner getSourceInclusionScanner( int staleMillis )
{
  SourceInclusionScanner scanner;

  if ( includes.isEmpty() &amp;amp;&amp;amp; excludes.isEmpty() )
  {
      scanner = new StaleSourceScanner( staleMillis );
  }
  else
  {
      if ( includes.isEmpty() )
      {
          includes.add( &quot;**/*.jamon&quot; );
      }
      scanner = new StaleSourceScanner( staleMillis, includes, excludes );
  }

  return scanner;
}
&lt;/pre&gt;
&lt;p&gt;If you&apos;re using Jamon and its Maven Plugin, you can view &lt;a href=&quot;http://sourceforge.net/tracker/index.php?func=detail&amp;amp;aid=3156388&amp;amp;group_id=138569&amp;amp;atid=741043&quot;&gt;my patch&lt;/a&gt; at SourceForge. If you&apos;re looking to include this functionality in your project, I invite you to look at the code I learned from in the Maven Compiler&apos;s &lt;a href=&quot;http://maven.apache.org/plugins/maven-compiler-plugin/xref/org/apache/maven/plugin/AbstractCompilerMojo.html#505&quot;&gt;AbstractCompilerMojo&lt;/a&gt; class.&lt;/p&gt;
&lt;p&gt;After making this change, I was able to reduce the build execution time by over 50%. Now it takes 20 seconds to hit the Jetty plugin and 42 seconds to finishing starting. Of course, in an ideal world, I&apos;d like to get this down to 20 seconds or less. Strangely enough, the easiest way to do this seems to be simple: &lt;strong&gt;use Linux&lt;/strong&gt;. 
&lt;/p&gt;
&lt;p&gt;
On the Linux desktop they provided me, it takes 12 seconds to hit the Jetty plugin and 23 seconds to finish starting. I&apos;d like to think this is a hardware thing, but it only get 20% faster on OS X when using an 8GB RAM + SSD machine (vs. a 4GB + 5400 drive). Since Overstock has &lt;a href=&quot;http://twitter.com/#!/mraible/status/22456049793499136&quot; title=&quot;I love it when clients give me a brand new MacBook Pro on my first day.&quot;&gt;provided me with a 4GB MacBook Pro&lt;/a&gt;, I&apos;m considering installing Ubuntu on it, just to see what the difference is.&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;http://www.flickr.com/photos/mraible/5310291219/&quot; title=&quot;Sun over the Snowbird by mraible, on Flickr&quot;&gt;&lt;img src=&quot;//farm6.static.flickr.com/5129/5310291219_ffe75d84a7_t.jpg&quot; width=&quot;100&quot; height=&quot;75&quot; alt=&quot;Sun over the Snowbird&quot; class=&quot;picture&quot;/&gt;&lt;/a&gt;
In related news, Overstock.com is looking to hire a &lt;a href=&quot;http://www.overstock.com/javajobs&quot;&gt;whole bunch of Java Developers&lt;/a&gt; this year. The &lt;a href=&quot;http://twitter.com/#!/sammyland/status/27427352032059392&quot;&gt;pictures of the new Provo office&lt;/a&gt; look pretty sweet. Of course, you can also work at HQ, which is a mere 25 minutes from some of the best skiing in the world. Personally, I think Colorado&apos;s powder is better, but I can&apos;t argue with the convenience of no traffic. In addition to full-time gigs, they&apos;ve started hiring more remote contractors like myself, so they pretty much have something for everyone. So if you love Java, like to get some turns in before work, and aren&apos;t an asshole - you should 
&lt;script language=&quot;Javascript&quot; type=&quot;text/javascript&quot;&gt;
&lt;!--
document.write(&apos;&lt;a href=&quot;mai&apos;);
document.write(&apos;lto&apos;);
document.write(&apos;:&amp;#109;&amp;#97;&amp;#116;&amp;#116;&apos;);
document.write(&apos;@&apos;);
document.write(&apos;&amp;#114;&amp;#97;&amp;#105;&amp;#98;&amp;#108;&amp;#101;&amp;#100;&amp;#101;&amp;#115;&amp;#105;&amp;#103;&amp;#110;&amp;#115;&amp;#46;&amp;#99;&amp;#111;&amp;#109;&quot;&gt;&apos;);
document.write(&apos;contact me&lt;\/a&gt;&apos;);
// --&gt;
&lt;/script&gt;&lt;noscript&gt;&lt;a href=&quot;http://raibledesigns.com/contact.jsp&quot;&gt;contact me&lt;/a&gt;&lt;/noscript&gt;
 and I&apos;ll try to hook you up.&lt;/p&gt;
&lt;p id=&quot;update&quot;&gt;&lt;strong&gt;Update:&lt;/strong&gt; After writing this post, I received an email from &lt;a href=&quot;http://www.linkedin.com/pub/neil-hartner/4/800/852&quot;&gt;Neil Hartner&lt;/a&gt; questioning these numbers. Basically, he was able to get his MacBook Pro to run just as fast as Linux. Turns out, the reason my Mac was so much slower was because JRebel was configured in my MAVEN_OPTS. &lt;a href=&quot;http://www.zeroturnaround.com/jrebel/faq/#Does_JRebel_slow_my_system_down&quot;&gt;JRebel&apos;s FAQ&lt;/a&gt; does state the following:
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
&lt;strong&gt;Does JRebel make the server start up slower?&lt;/strong&gt;&lt;br/&gt;
JRebel needs to do more work on startup (search more places for classes and resources, instrument classes, etc), so some slowdown can be expected. If it&apos;s larger than 50% please contact support@zeroturnaround.com.
&lt;/p&gt;
&lt;p&gt;
Since it&apos;s right around 50% slower, I guess there&apos;s no reason to call them. My guess is the best thing to do is remove JRebel from MAVEN_OPTS, but have an alias that can enable it, or simply run it from your IDE.&lt;/p&gt;&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_2_1_milestone_2</guid>
    <title>AppFuse 2.1 Milestone 2 Released</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_2_1_milestone_2</link>
        <pubDate>Mon, 15 Nov 2010 15:28:57 -0700</pubDate>
    <category>Java</category>
    <category>myfaces</category>
    <category>appfuse-light</category>
    <category>webframeworks</category>
    <category>java</category>
    <category>appfuse</category>
    <category>jsf</category>
    <category>springmvc</category>
    <category>freemarker</category>
    <category>wicket</category>
    <category>maven2</category>
    <category>spring</category>
    <category>maven</category>
    <category>stripes</category>
    <category>hibernate</category>
    <category>java5</category>
    <category>ibatis</category>
    <category>archetypes</category>
    <category>jpa</category>
    <category>tapestry</category>
    <category>maven3</category>
    <category>struts2</category>
            <description>I&apos;m pleased to announce the 2nd milestone release of AppFuse 2.1. This release includes upgrades to all dependencies to bring them up-to-date with their latest releases. Most notable are Spring 3 and Struts 2.1. This release fixes many issues with archetypes and contains many improvements to support Maven 3. For more details on specific changes see the &lt;a href=&quot;http://appfuse.org/display/APF/Release+Notes+2.1.0+M2&quot;&gt;2.1.0 M2 release notes&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;What is AppFuse?&lt;/strong&gt;&lt;br/&gt;
AppFuse is an open source project and application that uses open source frameworks to help you develop Web applications quickly and efficiently. It was originally developed to eliminate the ramp-up time when building new web applications. At its core, AppFuse is a project skeleton, similar to the one that&apos;s created by your IDE when you click through a wizard to create a new web project. If you use &lt;a href=&quot;http://raibledesigns.com/rd/entry/using_jrebel_with_intellij_idea&quot;&gt;JRebel with AppFuse&lt;/a&gt;, you can achieve zero-turnaround in your project and develop features without restarting the server.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;
Release Details&lt;/strong&gt;&lt;br/&gt;
Archetypes now include all the source for the web modules so using jetty:run and your IDE will work much smoother now. The backend is still embedded in JARs, enabling you to choose with persistence framework (Hibernate, iBATIS or JPA) you&apos;d like to use. If you want to modify the source for that, &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+Core+Classes&quot;&gt;add the core classes to your project&lt;/a&gt; or run &quot;appfuse:full-source&quot;.
&lt;/p&gt;
&lt;p&gt;
AppFuse comes in a number of different flavors. It offers &quot;light&quot;, &quot;basic&quot; and &quot;modular&quot; and archetypes. Light archetypes use an embedded H2 database and contain a simple CRUD example. In the final 2.1.0 release, the light archetypes will allow code generation like the basic and modular archetypes. Basic archetypes have web services using CXF, authentication from Spring Security and features including signup, login, file upload and CSS theming. Modular archetypes are similar to basic archetypes, except they have multiple modules which allows you to separate your services from your web project.
&lt;/p&gt;
&lt;p&gt;
AppFuse provides &lt;a href=&quot;http://static.appfuse.org/archetype.html&quot;&gt;archetypes&lt;/a&gt; for JSF, Spring MVC, Struts 2 and Tapestry 5. The light archetypes are available for these frameworks, as well as for Spring MVC + FreeMarker, Stripes and Wicket.
&lt;/p&gt;
&lt;p&gt;
Please note that this release does not contain updates to the documentation. Code generation will work, but it&apos;s likely that some content in the &lt;a href=&quot;http://appfuse.org/display/APF/Tutorials&quot;&gt;tutorials&lt;/a&gt; won&apos;t match. For example, you can use annotations (vs. XML) for Spring MVC and Tapestry is a whole new framework. I&apos;ll be working on documentation over the next several weeks in preparation for the 2.1 final release.
&lt;/p&gt;
&lt;p&gt;
For information on creating a new project, please see the &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+QuickStart&quot;&gt;QuickStart Guide&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
If you have questions about AppFuse, please read the &lt;a href=&quot;http://appfuse.org/display/APF/FAQ&quot;&gt;FAQ&lt;/a&gt; or join the &lt;a href=&quot;http://appfuse.org/display/APF/Mailing+Lists&quot;&gt;user mailing list&lt;/a&gt;. If you find bugs, please &lt;a href=&quot;http://issues.appfuse.org/browse/APF&quot;&gt;create an issue in JIRA&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Thanks to everyone for their help contributing patches, writing documentation and participating on the mailing lists.
</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/versioning_static_assets_with_urlrewritefilter</guid>
    <title>Versioning Static Assets with UrlRewriteFilter</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/versioning_static_assets_with_urlrewritefilter</link>
        <pubDate>Fri, 4 Jun 2010 09:27:42 -0600</pubDate>
    <category>Java</category>
    <category>java</category>
    <category>webperformance</category>
    <category>performance</category>
    <category>highperformance</category>
    <category>apache</category>
    <category>jsp</category>
    <category>mod_rewrite</category>
    <category>urlrewritefilter</category>
    <category>maven</category>
            <description>A few weeks ago, a &lt;a href=&quot;http://www.linkedin.com/in/ericmitchell&quot;&gt;co-worker&lt;/a&gt; sent me interesting email after talking with the &lt;a href=&quot;http://zoompf.com/&quot;&gt;Zoompf CEO&lt;/a&gt; at &lt;a href=&quot;http://jsconf.us/2010/&quot;&gt;JSConf&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
One interesting tip mentioned was how we querystring the version on our scripts and css. Apparently this doesn&apos;t always cache the way we expected it would (some proxies will never cache an asset if it has a querystring).  The &lt;a href=&quot;http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/&quot;&gt;recommendation is to rev the filename itself&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;This article explains how we implemented a &quot;cache busting&quot; system in our application with Maven and the UrlRewriteFilter. We originally used querystring in our implementation, but switched to filenames after reading Souders&apos; recommendation. That part was figured out by my esteemed colleague &lt;a href=&quot;http://software.druidhillroad.com/&quot;&gt;Noah Paci&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Our Requirements&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Make the URL include a version number for each static asset URL (JS, CSS and SWF) that serves to expire a client&apos;s cache of the asset. 
&lt;/li&gt;&lt;li&gt;Insert the version number into the application so the version number can be included in the URL.
&lt;/li&gt;&lt;li&gt;Use a random version number when in development mode (based on running without a packaged war) so that developers will not need to clear their browser cache when making changes to static resources.  The random version number should match the production version number formats which is currently: x.y-SNAPSHOT-revisionNumber
&lt;/li&gt;&lt;li&gt;When running in production, the version number/cachebust is computed once (when a Filter is initialized).  In development, a new cachebust is computed on each request.
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;In our app, we&apos;re using Maven, Spring and JSP, but the latter two don&apos;t really matter for the purposes of this discussion.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Implementation Steps&lt;/strong&gt;
&lt;br/&gt;
1. First we added the &lt;a href=&quot;http://mojo.codehaus.org/buildnumber-maven-plugin/&quot;&gt;buildnumber-maven-plugin&lt;/a&gt; to our project&apos;s pom.xml so the build number is calculated from SVN.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;buildnumber-maven-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.0-beta-4&amp;lt;/version&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;phase&amp;gt;validate&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;create&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;doCheck&amp;gt;false&amp;lt;/doCheck&amp;gt;
        &amp;lt;doUpdate&amp;gt;false&amp;lt;/doUpdate&amp;gt;
        &amp;lt;providerImplementations&amp;gt;
            &amp;lt;svn&amp;gt;javasvn&amp;lt;/svn&amp;gt;
        &amp;lt;/providerImplementations&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;2. Next we used the maven-war-plugin to add these values to our WAR&apos;s MANIFEST.MF file.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.0.2&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;archive&amp;gt;
            &amp;lt;manifest&amp;gt;
                &amp;lt;addDefaultImplementationEntries&amp;gt;true&amp;lt;/addDefaultImplementationEntries&amp;gt;
            &amp;lt;/manifest&amp;gt;
            &amp;lt;manifestEntries&amp;gt;
                &amp;lt;Implementation-Version&amp;gt;${project.version}&amp;lt;/Implementation-Version&amp;gt;
                &amp;lt;Implementation-Build&amp;gt;${buildNumber}&amp;lt;/Implementation-Build&amp;gt;
                &amp;lt;Implementation-Timestamp&amp;gt;${timestamp}&amp;lt;/Implementation-Timestamp&amp;gt;
            &amp;lt;/manifestEntries&amp;gt;
        &amp;lt;/archive&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;3. Then we configured a Filter to read the values from this file on startup. If this file doesn&apos;t exist, a default version number of &quot;1.0-SNAPSHOT-{random}&quot; is used. Otherwise, the version is calculated as ${project.version}-${buildNumber}.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
private String buildNumber = null;

...
@Override
public void initFilterBean() throws ServletException {
    try {
        InputStream is = 
            servletContext.getResourceAsStream(&quot;/META-INF/MANIFEST.MF&quot;);
        if (is == null) {
            log.warn(&quot;META-INF/MANIFEST.MF not found.&quot;);
        } else {
            Manifest mf = new Manifest();
            mf.read(is);
            Attributes atts = mf.getMainAttributes();
            buildNumber = atts.getValue(&quot;Implementation-Version&quot;) + &quot;-&quot; + atts.getValue(&quot;Implementation-Build&quot;);
            log.info(&quot;Application version set to: &quot; + buildNumber);
        }
     } catch (IOException e) {
        log.error(&quot;I/O Exception reading manifest: &quot; + e.getMessage());
     }
}

...

    // If there was a build number defined in the war, then use it for
    // the cache buster. Otherwise, assume we are in development mode 
    // and use a random cache buster so developers don&apos;t have to clear 
    // their browswer cache.
    requestVars.put(&quot;cachebust&quot;, buildNumber != null ? buildNumber : &quot;1.0-SNAPSHOT-&quot; + new Random().nextInt(100000));
&lt;/pre&gt;
&lt;p&gt;4. We then used the &quot;cachebust&quot; variable and appended it to static asset URLs as indicated below.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;c:set var=&quot;version&quot; scope=&quot;request&quot; 
    value=&quot;${requestScope.requestConfig.cachebust}&quot;/&gt;
&amp;lt;c:set var=&quot;base&quot; scope=&quot;request&quot;
    value=&quot;${pageContext.request.contextPath}&quot;/&gt;

&amp;lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; 
    href=&quot;${base}/v/${version}/assets/css/style.css&quot; media=&quot;all&quot;/&gt;

&amp;lt;script type=&quot;text/javascript&quot; 
    src=&quot;${base}/v/${version}/compressed/jq.js&quot;&gt;&amp;lt;/script&gt;
&lt;/pre&gt;
&lt;p&gt;
The injection of /v/[CACHEBUSTINGSTRING]/(assets|compressed) eventually has to map back to the actual asset (that does not include the two first elements of the URI). The application must remove these two elements to map back to the actual asset. To do this, we use the &lt;a href=&quot;http://tuckey.org/urlrewrite/&quot;&gt;UrlRewriteFilter&lt;/a&gt;. The UrlRewriteFilter is used (instead of Apache&apos;s &lt;a href=&quot;http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html&quot;&gt;mod_rewrite&lt;/a&gt;) so when developers run locally (using &lt;em&gt;mvn jetty:run&lt;/em&gt;) they don&apos;t have to configure Apache.
&lt;/p&gt;
&lt;p&gt;5. In our application, &quot;/compressed/&quot; is mapped to &lt;a href=&quot;http://code.google.com/p/wro4j/&quot;&gt;wro4j&lt;/a&gt;&apos;s WroFilter. In order to get UrlRewriteFilter and WroFilter to work with this setup, the WroFilter has to accept FORWARD and REQUEST dispatchers.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;filter-mapping&amp;gt;
    &amp;lt;filter-name&amp;gt;rewriteFilter&amp;lt;/filter-name&amp;gt;
    &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;
&amp;lt;/filter-mapping&amp;gt;

&amp;lt;filter-mapping&amp;gt;
    &amp;lt;filter-name&amp;gt;WebResourceOptimizer&amp;lt;/filter-name&amp;gt;
    &amp;lt;url-pattern&amp;gt;/compressed/*&amp;lt;/url-pattern&amp;gt;
    &amp;lt;dispatcher&amp;gt;FORWARD&amp;lt;/dispatcher&amp;gt;
    &amp;lt;dispatcher&amp;gt;REQUEST&amp;lt;/dispatcher&amp;gt;
&amp;lt;/filter-mapping&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
Once this was configured, we added the following rules to our urlrewrite.xml to allow rewriting of any assets or compressed resource request back to its &quot;correct&quot; URL.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;rule match-type=&quot;regex&quot;&amp;gt;
    &amp;lt;from&amp;gt;^/v/&amp;#91;0-9A-Za-z_.\-&amp;#93;+/assets/(.*)$&amp;lt;/from&amp;gt;
    &amp;lt;to&amp;gt;/assets/$1&amp;lt;/to&amp;gt;
&amp;lt;/rule&amp;gt;
&amp;lt;rule match-type=&quot;regex&quot;&amp;gt;
    &amp;lt;from&amp;gt;^/v/&amp;#91;0-9A-Za-z_.\-&amp;#93;+/compressed/(.*)$&amp;lt;/from&amp;gt;
    &amp;lt;to&amp;gt;/compressed/$1&amp;lt;/to&amp;gt;
&amp;lt;/rule&amp;gt;
&amp;lt;rule&amp;gt;
    &amp;lt;from&amp;gt;/compressed/**&amp;lt;/from&amp;gt;
    &amp;lt;to&amp;gt;/compressed/$1&amp;lt;/to&amp;gt;
&amp;lt;/rule&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Of course, you can also do this in Apache. This is what it might look like in your vhost.d file:
&lt;/p&gt;
&lt;pre&gt;
RewriteEngine    on
RewriteLogLevel  0!
RewriteLog       /srv/log/apache22/app_rewrite_log
RewriteRule      ^/v/[.A-Za-z0-9_-]+/assets/(.*) /assets/$1 [PT]
RewriteRule      ^/v/[.A-Za-z0-9_-]+/compressed/(.*) /compressed/$1 [PT]
&lt;/pre&gt;
&lt;p&gt;
Whether it&apos;s a good idea to implement this in Apache or using the UrlRewriteFilter is up for debate. If we&apos;re able to do this with the UrlRewriteFilter, the benefit of doing this at all in Apache is questionable, especially since it creates a duplicate of code.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/what_s_new_in_maven</guid>
    <title>What&apos;s New in Maven 3.0 with Matthew McCullough</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/what_s_new_in_maven</link>
        <pubDate>Thu, 13 May 2010 15:54:21 -0600</pubDate>
    <category>Java</category>
    <category>denverjug</category>
    <category>maven</category>
    <category>polyglot</category>
    <category>matthewmccullough</category>
    <category>denver</category>
    <category>maven3</category>
            <description>Last night, I attended the &lt;a href=&quot;http://denverjug.org&quot;&gt;Denver JUG&lt;/a&gt; meeting to hear some excellent talks by &lt;a href=&quot;http://ambientideas.com/blog/&quot;&gt;Matthew McCullough&lt;/a&gt; and &lt;a href=&quot;http://www.augusttechgroup.com/tim/blog/&quot;&gt;Tim Berglund&lt;/a&gt;. I took notes during Matthew&apos;s talk, but my battery ran out before Tim&apos;s talk started. Below are my notes.
&lt;/p&gt;
&lt;p style=&quot;border-top: 1px dotted silver; padding-top: 5px&quot;&gt;
Matthew started out by described the differences between Maven 2 and Maven 3. As he began, he emphasized it wasn&apos;t a beginner talk, but mostly for existing Maven users that understand how to read a pom.xml and such. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;The Roadmap&lt;/strong&gt;&lt;br/&gt;
Commits  to Maven 3 have been happening for the last 3 years. Matthew is not an employee of &lt;a href=&quot;http://sonatype.com&quot;&gt;Sonatype&lt;/a&gt;, but he mentioned their name quite a bit in his talk. Sonatype has hired several committers (7 that Matthew knows of by name) that now work on Maven 3 full-time. For compatibility with Maven 2, the project has 450 integration tests and they test it against 100s of Maven 2 projects. Maven 3 has plugin classloader partitioning and a &lt;em&gt;legacy simulation&lt;/em&gt; layer for old plugins. 
&lt;/p&gt;
&lt;p&gt;
The main improvement in Maven 3 is &lt;em&gt;speed&lt;/em&gt;. It&apos;s been performance tuned to be 50% to 400% faster. Benchmarks (guaranteed by integration tests) include better: Disk I/O, Network I/O, CPU and Memory. Another new feature is extensibility so Maven is a better library rather than just a command-line tool. Now there&apos;s a library and APIs that you can use to do the things that Maven does. Plexus has been replaced with Guice and it&apos;s now much easier to embed Maven (&lt;a href=&quot;http://polyglot.sonatype.org&quot;&gt;Polyglot Maven&lt;/a&gt; and &lt;a href=&quot;http://shell.sonatype.org/&quot;&gt;Maven Shell&lt;/a&gt; are examples of this).
&lt;/p&gt;
&lt;p&gt;Below are a number of other changes between Maven 2 and Maven 3.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Syntax: pom.xml still uses &amp;lt;modelVersion&gt;4.0.0&amp;lt;/modelVersion&gt; so it can be a drop-in replacement for Maven 2 projects.&lt;/li&gt;
&lt;li&gt;Validations: poms are heavily validated against common mistakes, warns when plugin versions are not specified (use &lt;strong&gt;mvn validate&lt;/strong&gt; to see issues), blocks duplicate dependencies (examined in same POM only, conflict resolution used otherwise).&lt;/li&gt;
&lt;li&gt;Help URLs: wiki page URLs now shown for all error messages. One of the first Apache projects to do this.&lt;/li&gt;
&lt;li&gt;Removals: profiles.xml external file support removed, Maven 1.0 repository support removed &amp;lt;layout&gt;legacy&amp;lt;/layout&gt; (it&apos;s been 5 years since any commits to Maven 1).&lt;/li&gt;
&lt;li&gt;Behavior: SNAPSHOTs always deployed with date-stamps, artifact resolution caching has been improved to do less checking (override with &lt;strong&gt;mvn &amp;lt;phase&gt; -U&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Plugins: version auto-selection favors RELEASEs over SNAPSHOTs (opposite for Maven 2), versions cannot be specified as RELEASE or LATEST, plugins only resolved from &amp;lt;pluginRepository&gt; locations.&lt;/li&gt;
&lt;li&gt;See the &lt;a href=&quot;https://cwiki.apache.org/MAVEN/maven-3x-plugin-compatibility-matrix.html&quot;&gt;Plugin Compatibility Matrix&lt;/a&gt; to see if your favorite plugins are compatible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Maven 3 hopes to be a drop-in replacement for Maven 2, but non backwards-compatible changes will be happening in Maven 3.1. It&apos;s anticipated release is Q1 of 2011 and will likely contain the following features.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&quot;Mixins&quot; for direct dependencies&lt;/li&gt;
&lt;li&gt;Site plugin takes over &amp;lt;reporting&gt;&lt;/li&gt;
&lt;li&gt;Backwards compatibility by &amp;lt;modelVersion&lt;/li&gt;
&lt;li&gt; There&apos;s a good chance 3.1 breaks compatibility with legacy POMs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Another new thing in Maven 3 is &lt;strong&gt;Toolchain&lt;/strong&gt;. Toolchain a common way to configure your JDK for multiple plugins. There are only a handful of plugins that are toolchain-enabled. User tool chain definitions are defined in ~/.m2/toolchains.xml. To use different toolchains (JDKs), you specify a vendor and version as part of your plugin configuration. 
&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://shell.sonatype.org&quot;&gt;Maven Shell&lt;/a&gt; is a high performance console that&apos;s a Maven 3 add-on. It&apos;s &lt;a href=&quot;http://github.com/sonatype/mvnsh&quot;&gt;hosted at GitHub&lt;/a&gt; to make community contributions easier. It goes on your command line and it offers syntax highlighting and context-sensitive help (by typing ? at the command prompt).
&lt;/p&gt;
&lt;p&gt;
Another major improvement in Maven 3 is &lt;a href=&quot;http://polyglot.sonatype.org&quot;&gt;Polyglot Maven&lt;/a&gt;. Tools like Gant and Buildr have made Maven look ancient, but they&apos;ve also given it a good challenge. Maven 3 is likely to leapfrog these tools because of its ability to use different languages for your build configuration. Currently, 6 languages are supported. Polyglot Maven is a super-set distribution of Maven 3. It&apos;s not shipped with Maven 3 core because it contains all the other language implementations and is quite large. Polyglot Maven also contains a &lt;em&gt;translate&lt;/em&gt; tool that allows you to convert any-to-any language. It has a DSL framework with Macros and Lifecycle Hooks. Macros allows for more concise syntax. 
&lt;/p&gt;
&lt;p&gt;After talking about Polyglot Maven a bit, Matthew shows us a demo translating pom.xml to pom.yaml and then running the build. After that, he showed us examples of what a pom looks like when defined in Clojure, Scala and Groovy. Someone asked about file parsing performance and Matthew said different languages would cause a single-digit performance difference as part of your build process. Personally, I can&apos;t help but think any non-XML parser would be faster than the XML parser.
&lt;/p&gt;
&lt;p&gt;In regards to &lt;a href=&quot;http://m2eclipse.sonatype.org/&quot;&gt;m2eclipse&lt;/a&gt;, a new drop (0.10) occurred a few weeks ago and it&apos;s one of the highest quality releases to date. It has major refactoring and many performance improvements.&lt;/p&gt;
&lt;p&gt;For sample Maven projects see &lt;a href=&quot;http://github.com/matthewmccullough/maven-training&quot;&gt;Matthew&apos;s Maven Samples&lt;/a&gt;.
&lt;/p&gt;
&lt;p style=&quot;border-top: 1px dotted silver; padding-top: 10px&quot;&gt;I very much enjoyed Matthew&apos;s talk, both because of his presentation techniques and because he had a lot of good information. While I&apos;ve tried Maven 3 and Shell in the past, I&apos;ve been newly inspired to start using them again on a daily basis. 
&lt;/p&gt;
&lt;p&gt;Tim&apos;s talk on Decision Making was also excellent. The biggest things I learned were that conflict is good (idea-wise, not personal) and things to look out for between teams (fault lines). Hopefully both Tim and Matthew post their slides so I can link to them here. 
</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/software_quality_the_quest_for</guid>
    <title>Software Quality: The Quest for the Holy Grail?</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/software_quality_the_quest_for</link>
        <pubDate>Wed, 17 Mar 2010 15:00:46 -0600</pubDate>
    <category>Java</category>
    <category>tattletale</category>
    <category>tssjs</category>
    <category>maven</category>
    <category>jboss</category>
    <category>ivy</category>
            <description>This afternoon, I attended a &lt;a href=&quot;http://javasymposium.techtarget.com/html/tools_tech.html#JPedersenQuality&quot;&gt;session on software quality&lt;/a&gt; by &lt;a href=&quot;http://community.jboss.org/people/jesper.pedersen&quot;&gt;Jesper Pedersen&lt;/a&gt; at TSSJS. Jesper is a Core Developer at JBoss by Red Hat. He&apos;s the project lead of JBoss JCA, Tattletale, Papaki and JBoss Profiler 2. He&apos;s also currently the chairman of the Boston JBoss User Group. In this session, Jesper hopes to define basic requirements for a development environment and offer ideas on how to clean up a messy project.
&lt;/p&gt;
&lt;p&gt;
Is software quality a friend or a foe? By implementing software quality processes, are you introducing unnecessary overhead? Development platforms are &lt;em&gt;different&lt;/em&gt; today. We write a lot more business-specific code. We depend on standard frameworks for the core functionality. We depend on vendors to implement the standards correctly. We also depend on vendors to provide the necessary integration layer.
&lt;/p&gt;
&lt;p&gt;Since the platform is now a large slice of the pie, we must make sure we know where the issue is located. We must have proper integration tests; we must manage dependencies. Today, we must treat dependencies as if they are part of the application.
&lt;/p&gt;
&lt;p&gt;
Defining the platform for your project helps narrow down the dependencies for your project. The platform is composed of corporate guidelines, standards, vendors and backend systems that you have to integrate with. Documentation is key for a successful project. Key documents types: User Guide, Developer Guide, API Guide, Architect Design, Implementation and Test.
&lt;/p&gt;
&lt;p&gt;It helps to define a project-wide configuration management system. Define a code-formatting guide will add consistency in your source tree. Also make sure you have separate build, test and execution environments. Use a Maven repository for your dependencies; both to support your project&apos;s artifacts as well as vendor artifacts.&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;&quot;Maven today is an industry standard.&quot; -- Jesper Pederson
&lt;/p&gt;
&lt;p&gt;Define your tool chain as you would for your application. Back your Maven repository with SCM tools like Subversion or Git. For testing, use JUnit (unit testing), Corbertura (test coverage) and Hudson (continuous integration). Furthermore, you can add Checkstyle and Findbugs to verify coding conventions and find basic issues with code.
&lt;/p&gt;
&lt;p&gt;For the build environment, you need to make sure your dependency metadata is correct. Also, make sure you use the best practices for your given build tool. For example, with Maven and Ivy, it&apos;s a good idea to extract the version numbers into a common area of your pom.xml/build.xml so you can easily view all the versions in use. After you&apos;ve done this, you can externalize the version information from the environment. Watch out for transitive dependencies as they can be tricky. Make sure you know what gets pulled in. Use enforcers to approve/ban dependencies or turn it off (Ivy). You can also vote for &lt;a href=&quot;http://jira.codehaus.org/browse/MNG-2315&quot;&gt;MNG-2315&lt;/a&gt;. Finally, snapshot dependencies are evil: define your release process so that releases are easy.
&lt;/p&gt;
&lt;p&gt;What can you do if your project is already a mess? Signs that your project is a mess: you look at your platform as a big black box, you use different dependencies than your deployment platform or you don&apos;t have integration tests for sub-systems or dependencies. To fix this, you can use a tool to get an overview of the entire project. Enter &lt;a href=&quot;http://www.jboss.org/tattletale&quot;&gt;Tattletale&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Tattletale can give you an overview of your dependencies (Ant and Maven integration). It&apos;s a static analysis tool that doesn&apos;t depend on metadata, scanning your class files instead. Using Tattletale, you can produce a number of reports about your dependencies, what they&apos;re dependent on and what&apos;s dependent on you.&lt;/p&gt;
&lt;p&gt;To maintain the lead in your project, make sure to define a checklist for each stage of your development cycle. Do reviews on documentation, architecture, component design and code. Enforce your rules of your project with your build system.&lt;/p&gt;
&lt;p&gt;Jesper&apos;s final thoughts: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Maintaining dependencies for a software project can be a tricky task.&lt;/li&gt;
&lt;li&gt;Using an Open Source platform as the foundation will ease the investigation of issues and increase trust.&lt;/li&gt;
&lt;li&gt;Defining a project-wide tool chain is key.&lt;/li&gt;
&lt;li&gt;Enforce all the rules on the project (better up-front than &quot;fixing it&quot; afterwards)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As &lt;a href=&quot;http://twitter.com/dustyp/status/10637304518&quot;&gt;Dusty mentioned&lt;/a&gt;, this session has a lot of good (basic) information, but there wasn&apos;t much new stuff.  My team is using many of the technologies and practices that Jesper has mentioned. I guess that&apos;s validation that we&apos;re doing it right. I&apos;ve heard of Tattletale, but never had a need for it since I haven&apos;t been on any &quot;messy&quot; projects recently.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_2_1_milestone_1</guid>
    <title>AppFuse 2.1 Milestone 1 Released</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_2_1_milestone_1</link>
        <pubDate>Thu, 19 Nov 2009 07:16:36 -0700</pubDate>
    <category>Java</category>
    <category>webframeworks</category>
    <category>tapestry</category>
    <category>archetypes</category>
    <category>appfuse-light</category>
    <category>appfuse</category>
    <category>freemarker</category>
    <category>java</category>
    <category>wicket</category>
    <category>maven2</category>
    <category>spring</category>
    <category>springmvc</category>
    <category>jsf</category>
    <category>stripes</category>
    <category>maven</category>
    <category>struts2</category>
    <category>hibernate</category>
    <category>java5</category>
    <category>myfaces</category>
    <category>ibatis</category>
    <category>jpa</category>
            <description>&lt;a href=&quot;http://appfuse.org&quot;&gt;&lt;img src=&quot;//appfuse.dev.java.net/images/icon.gif&quot; class=&quot;picture&quot; style=&quot;border: 0&quot;&gt;&lt;/a&gt;
The AppFuse Team is pleased to announce the first milestone release of AppFuse 2.1. This release includes upgrades to all dependencies to bring them up-to-date with their latest releases. Most notable are &lt;a href=&quot;http://raibledesigns.com/rd/entry/upgrading_hibernate_to_3_4&quot;&gt;Hibernate&lt;/a&gt;, &lt;a href=&quot;http://raibledesigns.com/rd/entry/moving_from_spring_s_xml&quot;&gt;Spring&lt;/a&gt; and Tapestry 5. 
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What is AppFuse?&lt;/strong&gt;&lt;br/&gt;
AppFuse is an open source project and application that uses open source tools built on the Java platform to help you develop Web applications quickly and efficiently. It was originally developed to eliminate the ramp-up time found when building new web applications for customers. At its core, AppFuse is a project skeleton, similar to the one that&apos;s created by your IDE when you click through a wizard to create a new web project.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Release Details&lt;/strong&gt;&lt;br/&gt;
&lt;a href=&quot;http://static.appfuse.org/archetypes.html&quot;&gt;Archetypes&lt;/a&gt; now include all the source for the web modules so using &lt;em&gt;jetty:run&lt;/em&gt; and your IDE will work much smoother now. The backend is still embedded in JARs, enabling you to choose which persistence framework (Hibernate, iBATIS or JPA) you&apos;d like to use. If you want to modify the source for that, &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+Core+Classes&quot;&gt;add the core classes to your project&lt;/a&gt; or run &lt;em&gt;appfuse:full-source&lt;/em&gt;. 
&lt;/p&gt;
&lt;p&gt;
In addition, AppFuse Light has been &lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_light_converted_to_maven&quot;&gt;converted to Maven&lt;/a&gt; and has archetypes available. AppFuse provides archetypes for JSF, Spring MVC, Struts 2 and Tapestry 5. The &lt;em&gt;light&lt;/em&gt; archetypes are available for these frameworks, as well as for Spring MVC + FreeMarker, Stripes and Wicket.
&lt;/p&gt;
&lt;p&gt;Other notable improvements:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Added &lt;a href=&quot;http://issues.appfuse.org/browse/APF-267&quot;&gt;Compass support&lt;/a&gt; thanks to a patch from &lt;a href=&quot;http://www.kimchy.org/&quot;&gt;Shay Banon&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Upgraded from &lt;a href=&quot;http://issues.appfuse.org/browse/APF-1125&quot;&gt;XFire to CXF&lt;/a&gt; for Web Services.&lt;/li&gt;
&lt;li&gt;Moved Maven repository to &lt;a href=&quot;https://docs.sonatype.com/display/NX/OSS+Repository+Hosting&quot;&gt;Sonatype&apos;s OSS Repository Hosting&lt;/a&gt; for snapshots and releasing to Maven Central. There are no longer any AppFuse-specific artifacts, all are available in central. Thanks to &lt;a href=&quot;http://sonatype.com&quot;&gt;Sonatype&lt;/a&gt; for this great service and its &lt;a href=&quot;http://raibledesigns.com/rd/entry/nexus_is_a_kick_ass&quot;&gt;excellent repository manager&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Upgraded to Canoo WebTest 3.0. &lt;em&gt;Now if we could just get its &lt;a href=&quot;http://people.apache.org/~sgoeschl/download/maven-plugins/webtest-maven-plugin/site/index.html&quot;&gt;Maven Plugin&lt;/a&gt; moved to Codehaus.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Added &lt;a href=&quot;http://raibledesigns.com/rd/entry/ajaxified_body&quot;&gt;Ajaxified Body&lt;/a&gt; to AppFuse Light archetypes.&lt;/li&gt;
&lt;li&gt;Infrastructure upgrades, including &lt;a href=&quot;http://issues.appfuse.org/&quot;&gt;JIRA 4&lt;/a&gt;, &lt;a href=&quot;http://appfuse.org/&quot;&gt;Confluence 3&lt;/a&gt;, &lt;a href=&quot;http://source.appfuse.org&quot;&gt;FishEye 2&lt;/a&gt;, &lt;a href=&quot;http://builds.appfuse.org&quot;&gt;Bamboo 2&lt;/a&gt; and &lt;a href=&quot;http://login.appfuse.org&quot;&gt;Crowd 1.6&lt;/a&gt;. Many thanks to &lt;a href=&quot;http://www.atlassian.com/c/NPOS/10160&quot;&gt;Atlassian&lt;/a&gt; and &lt;a href=&quot;http://contegix.com&quot;&gt;Contegix&lt;/a&gt; for their excellent products and services.&lt;/li&gt;
&lt;li&gt;For more details on specific changes see the &lt;a href=&quot;http://appfuse.org/display/APF/Release+Notes+2.1.0+M1&quot; title=&quot;Release Notes 2.1.0 M1&quot;&gt;release notes&lt;/a&gt;.
&lt;/ul&gt;
&lt;p&gt;Please note that this release does not contain updates to the documentation. Code generation will work, but it&apos;s likely that some content in the &lt;a href=&quot;http://appfuse.org/display/APF/Tutorials&quot;&gt;tutorials&lt;/a&gt; won&apos;t match. For example, you can use annotations (vs. XML) for dependency injection and Tapestry is a whole new framework. I&apos;ll be working on documentation over the next several weeks in preparation for Milestone 2.
&lt;/p&gt;
&lt;p&gt;AppFuse is available as several Maven archetypes. For information on creating a new project, please see the &lt;a href=&quot;http://appfuse.org/display/APF/AppFuse+QuickStart&quot; title=&quot;AppFuse QuickStart&quot;&gt;QuickStart Guide&lt;/a&gt;.
&lt;/p&gt;
&lt;p class=&quot;smokey&quot;&gt;
To learn more about AppFuse, please read Ryan Withers&apos; &lt;a href=&quot;http://www.ociweb.com/jnb/jnbMay2008.html&quot;&gt;Igniting your applications with AppFuse&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;The 2.x series of AppFuse has a minimum requirement of the following specification versions:&lt;/p&gt;

&lt;ul class=&quot;glassList&quot;&gt;
	&lt;li&gt;Java Servlet 2.4 and JSP 2.0 (2.1 for JSF)&lt;/li&gt;
	&lt;li&gt;Java 5+&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have questions about AppFuse, please read the &lt;a href=&quot;http://appfuse.org/display/APF/FAQ&quot; title=&quot;FAQ&quot;&gt;FAQ&lt;/a&gt; or join the &lt;a href=&quot;http://appfuse.org/display/APF/Mailing+Lists&quot; title=&quot;Mailing Lists&quot;&gt;user mailing list&lt;/a&gt;. If you find bugs, please &lt;a href=&quot;http://issues.appfuse.org/secure/CreateIssue!default.jspa&quot;&gt;create an issue in JIRA&lt;/a&gt;.&lt;/p&gt; 

&lt;p&gt;Thanks to everyone for their help contributing code, writing documentation, posting to the mailing lists, and logging issues. </description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/testing_gwt_libraries_with_selenium</guid>
    <title>Testing GWT Libraries with Selenium and Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/testing_gwt_libraries_with_selenium</link>
        <pubDate>Wed, 4 Nov 2009 22:09:27 -0700</pubDate>
    <category>Java</category>
    <category>maven-dependencies-plugin</category>
    <category>maven</category>
    <category>gwt</category>
    <category>cargo</category>
    <category>gwt-maven-plugin</category>
    <category>java</category>
    <category>selenium</category>
            <description>On Tuesday, I wrote about &lt;a href=&quot;http://raibledesigns.com/rd/entry/running_hosted_mode_in_gwt&quot;&gt;Running Hosted Mode in GWT Libraries&lt;/a&gt;.  Today I added an additional module to our project to run Selenium tests against our GWT library. In the process, I discovered some things I needed to modify in my GWT library&apos;s pom.xml. I&apos;m writing this post so others can use this setup to write GWT libraries and package them for testing with Selenium.
&lt;/p&gt;
&lt;p&gt;First of all, I noticed that when you&apos;re using the &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/&quot;&gt;GWT Maven Plugin&lt;/a&gt; with a JAR project, it doesn&apos;t automatically run gwt:compile or gwt:test in the compile and test phases. I had to explicitly configure the &lt;em&gt;compile&lt;/em&gt; goal to run in the &lt;em&gt;compile&lt;/em&gt; phase. I also had to add &amp;lt;webappDirectory&amp;gt; to the configuration to compile the JavaScript files into the &lt;em&gt;war&lt;/em&gt; directory.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;gwt-maven-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;module&amp;gt;org.appfuse.gwt.core.CoreUI&amp;lt;/module&amp;gt;
        &amp;lt;runTarget&amp;gt;index.html&amp;lt;/runTarget&amp;gt;
        &amp;lt;webappDirectory&amp;gt;war&amp;lt;/webappDirectory&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;phase&amp;gt;compile&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;compile&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;To package the generated JavaScript and index.html in the JAR, I added the following &amp;lt;resources&amp;gt; section to the maven-resources-plugin configuration I mentioned in my &lt;a href=&quot;http://raibledesigns.com/rd/entry/running_hosted_mode_in_gwt&quot;&gt;previous post&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;resource&amp;gt;
    &amp;lt;directory&amp;gt;war&amp;lt;/directory&amp;gt;
    &amp;lt;includes&amp;gt;
        &amp;lt;include&amp;gt;core.ui/**&amp;lt;/include&amp;gt;
        &amp;lt;include&amp;gt;index.html&amp;lt;/include&amp;gt;
    &amp;lt;/includes&amp;gt;
&amp;lt;/resource&amp;gt;
&lt;/pre&gt;
&lt;p&gt;
In addition, I discovered some javax.servlet.* classes in my JAR after running &quot;mvn package&quot;. I believe this is caused by the GWT plugin sucking these in when it compiles my ProxyServlet. I excluded them by adding the maven-jar-plugin.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-jar-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;excludes&amp;gt;
            &amp;lt;exclude&amp;gt;javax/servlet/**&amp;lt;/exclude&amp;gt;
        &amp;lt;/excludes&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;After doing this, I was able to publish my JAR with all the contents I needed to run Selenium tests against it. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Testing the GWT Library with Selenium&lt;/strong&gt;&lt;br/&gt;
The module that contains the Selenium tests is a WAR project that uses war overlays, Cargo and Selenium RC. You can read about the Maven setup I use for running Selenium tests in &lt;a href=&quot;http://raibledesigns.com/rd/entry/packaging_a_sofea_application_for&quot;&gt;Packaging a SOFEA Application for Distribution&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;
The major difference when testing a JAR (vs. a WAR), is I had to use the &lt;a href=&quot;http://maven.apache.org/plugins/maven-dependency-plugin/&quot;&gt;maven-dependency-plugin&lt;/a&gt; to unpack the JAR so its contents would get included in the WAR for testing. Below is the configuration I used to accomplish this:
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-dependency-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;id&amp;gt;unpack&amp;lt;/id&amp;gt;
            &amp;lt;phase&amp;gt;generate-sources&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;unpack&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;artifactItems&amp;gt;
                    &amp;lt;artifactItem&amp;gt;
                        &amp;lt;groupId&amp;gt;org.appfuse&amp;lt;/groupId&amp;gt;
                        &amp;lt;artifactId&amp;gt;gwt-core&amp;lt;/artifactId&amp;gt;
                        &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
                        &amp;lt;type&amp;gt;jar&amp;lt;/type&amp;gt;
                        &amp;lt;overWrite&amp;gt;false&amp;lt;/overWrite&amp;gt;
                        &amp;lt;excludes&amp;gt;META-INF/**,org/**,javax/**&amp;lt;/excludes&amp;gt;
                    &amp;lt;/artifactItem&amp;gt;
                &amp;lt;/artifactItems&amp;gt;
                &amp;lt;outputDirectory&amp;gt;
                    ${project.build.directory}/${project.build.finalName}
                &amp;lt;/outputDirectory&amp;gt;
            &amp;lt;/configuration&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Hopefully this will help you develop GWT libraries and run Selenium tests against them. If you have any suggestions for simplifying this configuration, please let me know.&lt;/p&gt;
&lt;div style=&quot;padding-top: 5px; border-top: 1px dotted silver; color: #666&quot;&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; I did considering a couple of other options for running Selenium tests against our GWT library:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add something to the existing project that 1) creates a WAR and 2) fires up Cargo/Selenium in a profile to test it.
&lt;/li&gt;
&lt;li&gt;Create the tests in a GWT (war) project that includes widgets from the library.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I decided on the solution documented above because it seemed like the best option.&lt;/p&gt;
&lt;/div&gt;&lt;p&gt;

</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/running_hosted_mode_in_gwt</guid>
    <title>Running Hosted Mode in GWT Libraries (when using Maven)</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/running_hosted_mode_in_gwt</link>
        <pubDate>Tue, 3 Nov 2009 09:37:07 -0700</pubDate>
    <category>Java</category>
    <category>hostedmode</category>
    <category>maven</category>
    <category>resources</category>
    <category>gwt-maven-plugin</category>
    <category>java</category>
    <category>ant</category>
    <category>gwt</category>
    <category>maven-gwt-plugin</category>
            <description>Earlier this year, I wrote about &lt;a href=&quot;http://raibledesigns.com/rd/entry/modularizing_gwt_applications_with_gwt&quot;&gt;Modularizing GWT Applications with GWT-Maven&lt;/a&gt;. Fast forward 8 months and I&apos;m still working with GWT and using this same technique. However, this time I&apos;m working with the &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/&quot;&gt;Maven GWT Plugin&lt;/a&gt; from Codehaus. In my last post, I wrote:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
The results of modularizing your application are beneficial (shared code) and detrimental (you have to &lt;code&gt;mvn install&lt;/code&gt; gwt-core whenever you make changes in shared classes). If you know of a way to configure the gwt-maven plugin to read sources from both gwt-core and gwt-webapp in hosted mode, I&apos;d love to hear about it. 
&lt;/p&gt;
&lt;p&gt;The good news is I found a solution for this, using the &lt;a href=&quot;http://mojo.codehaus.org/build-helper-maven-plugin/&quot;&gt;Builder Helper Maven Plugin&lt;/a&gt;. The GWT Maven Plugin&apos;s &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/user-guide/productivity.html&quot;&gt;
Productivity tip for multi-project setup&lt;/a&gt; has more information on how to configure this (note: we use IntelliJ and Eclipse on my project and did not need to configure this in a profile).&lt;/p&gt;
&lt;p&gt;
All was fine and dandy with this configuration until I wanted to be able to run hosted mode to develop/test everything in my library before including it in my main project. Luckily, you can still run &lt;strong&gt;mvn gwt:run&lt;/strong&gt; on a JAR project. However, when you configure your pom.xml so sources are included in your JAR, you run into an issue: your *.java files will be copied to &lt;em&gt;war/WEB-INF/classes&lt;/em&gt; and hosted mode will use these files as source rather than the ones you&apos;re editing in &lt;em&gt;src/main/java&lt;/em&gt;. 
&lt;/p&gt;
&lt;p&gt;To solve this, I changed my pom.xml to do two things:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;Only copy resources right before packaging (in the test phase).&lt;/li&gt;
&lt;li&gt;When packaging is complete, delete the *.java files from &lt;em&gt;war/WEB-INF/classes&lt;/em&gt; (using Ant).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Below is the XML I used to make this possible. Please let me know if you have a way to simplify this configuration.&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-resources-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.4.1&amp;lt;/version&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;phase&amp;gt;test&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;copy-resources&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;outputDirectory&amp;gt;${project.build.outputDirectory}&amp;lt;/outputDirectory&amp;gt;
                &amp;lt;resources&amp;gt;
                    &amp;lt;resource&amp;gt;
                        &amp;lt;directory&amp;gt;src/main/java&amp;lt;/directory&amp;gt;
                    &amp;lt;/resource&amp;gt;
                    &amp;lt;resource&amp;gt;
                        &amp;lt;directory&amp;gt;src/main/resources&amp;lt;/directory&amp;gt;
                    &amp;lt;/resource&amp;gt;
                &amp;lt;/resources&amp;gt;
            &amp;lt;/configuration&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-antrun-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.3&amp;lt;/version&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;phase&amp;gt;package&amp;lt;/phase&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;run&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
            &amp;lt;configuration&amp;gt;
                &amp;lt;tasks&amp;gt;
                    &amp;lt;delete&amp;gt;
                        &amp;lt;fileset dir=&quot;${project.build.outputDirectory}&quot; includes=&quot;**/*.java&quot;/&amp;gt;
                    &amp;lt;/delete&amp;gt;
                &amp;lt;/tasks&amp;gt;
            &amp;lt;/configuration&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This solution seems to work pretty well. As far as developing your library in hosted mode, you&apos;ll need to configure two *.gwt.xml files, one that doesn&apos;t have an &amp;lt;entry-point&amp;gt; defined and one that does. Configure the one with the entry point as the &amp;lt;module&amp;gt; in your gwt-maven-plugin configuration.&lt;/p&gt;
&lt;p&gt;As a side note, I found a few issues with the 1.1 version of the &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/user-guide/archetype.html&quot;&gt;Maven GWT Archetype&lt;/a&gt;. Below are the steps I used to fix these issues and upgrade to GWT 1.7.0 (I realize 1.7.1 is out, but gwt-dev-1.7.1-mac.jar &lt;a href=&quot;http://repo2.maven.org/maven2/com/google/gwt/gwt-dev/1.7.1/&quot;&gt;doesn&apos;t exist in Maven central&lt;/a&gt;).
&lt;/p&gt;
&lt;p&gt;First, create a new project by running the following from the command line:

&lt;pre&gt;
mvn archetype:generate \
  -DarchetypeGroupId=org.codehaus.mojo \
  -DarchetypeArtifactId=gwt-maven-plugin \
  -DarchetypeVersion=1.1 \
  -DgroupId=com.yourcompany \
  -DartifactId=gwt-project -Dversion=1.0-SNAPSHOT -B
&lt;/pre&gt;
&lt;p&gt;
After creating the project, you&apos;ll need to modify the pom.xml as follows:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Change the gwt-maven-plugin&apos;s version to &lt;strong&gt;1.1&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Change the ${gwtVersion} property to &lt;strong&gt;1.7.0&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;&amp;lt;runTarget&gt;Application.html&amp;lt;/runTarget&gt;&lt;/code&gt; to the &amp;lt;configuration&amp;gt; element of the plugin.&lt;/li&gt;
&lt;li&gt;Move Application.html and web.xml so they&apos;re under the &quot;war&quot; directory.&lt;/li&gt;
&lt;li&gt;Update Application.html to prepend the GWT module name in the &amp;lt;script&amp;gt; tag.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I hope these instructions help you create modular GWT projects with Maven. This setup is working great on my current project.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/packaging_a_sofea_application_for</guid>
    <title>Packaging a SOFEA Application for Distribution</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/packaging_a_sofea_application_for</link>
        <pubDate>Tue, 6 Oct 2009 01:17:38 -0600</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>selenium</category>
    <category>sofea</category>
    <category>tomcat</category>
    <category>maven</category>
    <category>waroverlays</category>
            <description>The project I&apos;m working on is a bit different from those I&apos;m used to. I&apos;m used to working on web applications that are hosted on servers and customers access with their browser. &lt;a href=&quot;http://en.wikipedia.org/wiki/Software_as_a_service&quot;&gt;SaaS&lt;/a&gt; if you will. My current client is different. They&apos;re a product company that sells applications and distributes them to customers via download and CD. Their customers install these applications on internal servers (supported servers include WebSphere, WebLogic and Tomcat).
&lt;/p&gt;
&lt;p&gt;
The product I&apos;m currently working on is structured as a &lt;a href=&quot;http://raibledesigns.com/rd/entry/re_life_above_the_service&quot; title=&quot;Service Oriented Front End Architecture&quot;&gt;SOFEA&lt;/a&gt; application and therefore consists of two separate modules - a backend and a frontend. Since it&apos;s installed in a servlet container, both modules are WARs and can be installed separately. 
&lt;/p&gt;
&lt;p&gt;
Building the backend and frontend as separate projects makes a lot of sense for two reasons:
&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;In development, different teams can work on the frontend and backend projects.&lt;/li&gt;
&lt;li&gt;Having them as separate projects allows them to be versioned separately.
&lt;/ul&gt;
&lt;p&gt;However, having them as two separate projects does make it a bit more difficult for distribution. I&apos;m writing this post to show you how I recently added support for distributing our application as 2 WARs &lt;em&gt;or&lt;/em&gt; 1 WAR using the power of Maven, war overlays and the &lt;a href=&quot;http://www.tuckey.org/urlrewrite/&quot;&gt;UrlRewriteFilter&lt;/a&gt;. 
&lt;/p&gt;
&lt;p id=&quot;projectsetup&quot;&gt;&lt;strong&gt;Project Setup&lt;/strong&gt;&lt;br/&gt;
First of all, we have several different Maven modules, but the most important ones are as follows:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;product-services&lt;/li&gt;
&lt;li&gt;product-client&lt;/li&gt;
&lt;li&gt;product-integration-tests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, our modules aren&apos;t really named &quot;product&quot;, but you get the point. The services project is really just a WAR project with Spring Security configured. It depends on other JAR modules that the services exist in. The client project is a GWT WAR that has a proxy servlet defined in its web.xml that makes it easier to develop. It also contains some UrlRewrite configuration that allows &lt;a href=&quot;http://code.google.com/p/gwt-log/&quot;&gt;GWT Log&apos;s&lt;/a&gt; Remote Logging feature to work. The proxy servlet is something we don&apos;t want to ship with our product, so we have a separate web.xml for production vs. development. We do the substitution using the maven-war-plugin:
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.0.2&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;!-- Production web.xml --&amp;gt;
        &amp;lt;webXml&amp;gt;src/main/resources/web.xml&amp;lt;/webXml&amp;gt;
        &amp;lt;warSourceDirectory&amp;gt;war&amp;lt;/warSourceDirectory&amp;gt;
        &amp;lt;!-- Exclude everything but urlrewrite JAR --&amp;gt;
        &amp;lt;warSourceExcludes&amp;gt;
            WEB-INF/lib/aop**,WEB-INF/lib/commons-**,WEB-INF/lib/gin-**,
            WEB-INF/lib/guice-**,WEB-INF/lib/gwt-**,WEB-INF/lib/gxt-**,
            WEB-INF/lib/junit-**
        &amp;lt;/warSourceExcludes&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p style=&quot;margin-left: 30px&quot;&gt;
&lt;em&gt;I could exclude WEB-INF/lib/** and WEB-INF/classes/**, but in my particular project, we still want UrlRewrite in standalone mode, and we have some i18n properties files in WEB-INF/classes that are served up for Selenium tests.&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;With this configuration, we have a services WAR and a client WAR that can be installed and used by clients. To collapse them into one and make it possible to ship a single war, I turned to our &lt;em&gt;product-integration-tests&lt;/em&gt; module. This module contains Selenium tests that test both types of distributions.
&lt;/p&gt;
&lt;p id=&quot;mergingwars&quot;&gt;
&lt;strong&gt;Merging 2 WARs into 1&lt;/strong&gt;&lt;br/&gt;
The most important thing in the product-integration-tests module is that it creates a single WAR. First of all, it uses &lt;code&gt;&amp;lt;packaging&gt;war&amp;lt;/packaging&gt;&lt;/code&gt; to make this possible. The rest is done using the following 3 steps.
&lt;/p&gt;
&lt;p&gt;
1. Its dependencies include the client and servlet WARs (and Selenium RC for testing).
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;dependencies&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;product-services&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
        &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
    &amp;lt;/dependency&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;product-client&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
        &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
    &amp;lt;/dependency&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.seleniumhq.selenium.client-drivers&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;selenium-java-client-driver&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;1.0.1&amp;lt;/version&amp;gt;
        &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
    &amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt;
&lt;/pre&gt;
&lt;p&gt;2. The WAR created excludes the &quot;integration-tests&quot; part of the name:
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;build&amp;gt;
    &amp;lt;finalName&amp;gt;product-${project.version}&amp;lt;/finalName&amp;gt;
    ...
&amp;lt;/build&amp;gt;
&lt;/pre&gt;
&lt;p&gt;3. WAR overlays are configured so the everything in the client&apos;s &lt;em&gt;WEB-INF&lt;/em&gt; directory is excluded from the merged WAR.
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;!-- http://maven.apache.org/plugins/maven-war-plugin/overlays.html --&amp;gt;
        &amp;lt;overlays&amp;gt;
            &amp;lt;overlay&amp;gt;
                &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;product-services&amp;lt;/artifactId&amp;gt;
                &amp;lt;excludes&amp;gt;
                    &amp;lt;!-- TODO: Rename to api.html (this is the Enunciate-generated documentation) --&amp;gt;
                    &amp;lt;exclude&amp;gt;index.html&amp;lt;/exclude&amp;gt;
                &amp;lt;/excludes&amp;gt;
            &amp;lt;/overlay&amp;gt;
            &amp;lt;!-- No server needed in product-client --&amp;gt;
            &amp;lt;overlay&amp;gt;
                &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;product-client&amp;lt;/artifactId&amp;gt;
                &amp;lt;excludes&amp;gt;
                    &amp;lt;exclude&amp;gt;WEB-INF/**&amp;lt;/exclude&amp;gt;
                &amp;lt;/excludes&amp;gt;
            &amp;lt;/overlay&amp;gt;
            &amp;lt;!-- Only include META-INF/context.xml to set the ROOT path --&amp;gt;
            &amp;lt;overlay&amp;gt;
                &amp;lt;excludes&amp;gt;
                    &amp;lt;exclude&amp;gt;WEB-INF/**&amp;lt;/exclude&amp;gt;
                &amp;lt;/excludes&amp;gt;
            &amp;lt;/overlay&amp;gt;
        &amp;lt;/overlays&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;That&apos;s it! Using this configuration, it&apos;s possible to distribute a Maven-based SOFEA project as single or multiple WARs. However, there are some nuances.
&lt;/p&gt;
&lt;p&gt;One thing you might notice is the reference to &lt;em&gt;META-INF/context.xml&lt;/em&gt; in the overlays configuration. This subtly highlights one issue I experienced when merging the WARs. In our GWT client, we&apos;re using URLs that point to our services at &lt;strong&gt;/product-services/*&lt;/strong&gt;. This works in development (via a proxy servlet) and when the WARs are installed separately - as long as the services WAR is installed at &lt;strong&gt;/product-services&lt;/strong&gt;. However, when they&apos;re merged, a little URL rewriting needs to happen. To do this, I added the UrlRewriteFilter to the product-services module and configured a simple rule. 
&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCENGINE urlrewrite PUBLIC &quot;-//tuckey.org//DTD UrlRewrite 3.0//EN&quot;
        &quot;http://tuckey.org/res/dtds/urlrewrite3.0.dtd&quot;&amp;gt;

&amp;lt;urlrewrite use-query-string=&quot;true&quot;&amp;gt;
    &amp;lt;!-- Used when services are merged into WAR with GWT client --&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;^/product-services/(.*)$&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot;&amp;gt;/$1&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
&amp;lt;/urlrewrite&amp;gt;
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;Because the services URLs point to the root (/product-services), the merged WAR has to be installed as the ROOT application. When you&apos;re using Cargo with Tomcat and want to deploy to ROOT, you have to have a &lt;em&gt;META-INF/context.xml&lt;/em&gt; with a path=&quot;&quot; reference (ref: &lt;a href=&quot;http://jira.codehaus.org/browse/CARGO-516&quot;&gt;CARGO-516&lt;/a&gt;).
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;Context path=&quot;&quot;/&amp;gt;
&lt;/pre&gt;
&lt;p&gt;It is possible to change the URLs in the client to be relative, but this gets seems to get messy when you&apos;re using separate WARs. When using relative URLs, I found I had to do solution using cross-context forwarding to get the results I wanted. Using a redirect instead of a forward worked, but resulted in the client talking to the server twice (once to get redirected, a second time for the actual call). Cross-context forwarding is supported by the UrlRewriteFilter and Tomcat, but I&apos;m not sure WebSphere or WebLogic support it. The best solution is probably to change the URLs dynamically at runtime, possibly using some sort of deferred binding technique. &lt;!--The upside to having the URLs start at a known location (/product-services) is that you could  install the merged WAR initially and install a newer product-services.war later to upgrade the services.--&gt;
&lt;/p&gt;
&lt;p id=&quot;testingwithselenium&quot;&gt;&lt;strong&gt;Testing with Cargo and Selenium&lt;/strong&gt;&lt;br/&gt;
Once I had everything merged, I wanted to configure Cargo and Selenium to allow testing both distribution types. If I installed all 3 wars at the same time, the &quot;product-services&quot; WAR would be used by both the product-client.war and the product.war, so I had to use profiles to allow installing the single merged WAR or both WARs. Below is the profile I used for starting Cargo, deploying the merged WAR, starting Selenium RC and running Selenium tests.&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
&amp;lt;properties&amp;gt;
    &amp;lt;cargo.container&amp;gt;tomcat6x&amp;lt;/cargo.container&amp;gt;
    &amp;lt;cargo.container.url&amp;gt;
        http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.20/bin/apache-tomcat-6.0.20.zip
    &amp;lt;/cargo.container.url&amp;gt;
    &amp;lt;cargo.host&amp;gt;localhost&amp;lt;/cargo.host&amp;gt;
    &amp;lt;cargo.port&amp;gt;23433&amp;lt;/cargo.port&amp;gt;
    &amp;lt;cargo.wait&amp;gt;false&amp;lt;/cargo.wait&amp;gt;
    &amp;lt;cargo.version&amp;gt;1.0&amp;lt;/cargo.version&amp;gt;

    &amp;lt;!-- *safari and *iexplore are additional options --&amp;gt;
    &amp;lt;selenium.browser&amp;gt;*firefox&amp;lt;/selenium.browser&amp;gt;
&amp;lt;/properties&amp;gt;
...
&amp;lt;profile&amp;gt;
    &amp;lt;id&amp;gt;itest-bamboo&amp;lt;/id&amp;gt;
    &amp;lt;activation&amp;gt;
        &amp;lt;activeByDefault&amp;gt;false&amp;lt;/activeByDefault&amp;gt;
    &amp;lt;/activation&amp;gt;
    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.cargo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;cargo-maven2-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;${cargo.version}&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;wait&amp;gt;${cargo.wait}&amp;lt;/wait&amp;gt;
                    &amp;lt;container&amp;gt;
                        &amp;lt;containerId&amp;gt;${cargo.container}&amp;lt;/containerId&amp;gt;
                        &amp;lt;log&amp;gt;${project.build.directory}/${cargo.container}/cargo.log&amp;lt;/log&amp;gt;
                        &amp;lt;zipUrlInstaller&amp;gt;
                            &amp;lt;url&amp;gt;${cargo.container.url}&amp;lt;/url&amp;gt;
                            &amp;lt;installDir&amp;gt;${installDir}&amp;lt;/installDir&amp;gt;
                        &amp;lt;/zipUrlInstaller&amp;gt;
                    &amp;lt;/container&amp;gt;
                    &amp;lt;configuration&amp;gt;
                        &amp;lt;home&amp;gt;${project.build.directory}/${cargo.container}/container&amp;lt;/home&amp;gt;
                        &amp;lt;properties&amp;gt;
                            &amp;lt;cargo.hostname&amp;gt;${cargo.host}&amp;lt;/cargo.hostname&amp;gt;
                            &amp;lt;cargo.servlet.port&amp;gt;${cargo.port}&amp;lt;/cargo.servlet.port&amp;gt;
                        &amp;lt;/properties&amp;gt;
                        &amp;lt;!-- Deploy as ROOT since XHR requests are made to /product-services --&amp;gt;
                        &amp;lt;deployables&amp;gt;
                            &amp;lt;deployable&amp;gt;
                                &amp;lt;properties&amp;gt;
                                    &amp;lt;context&amp;gt;ROOT&amp;lt;/context&amp;gt;
                                &amp;lt;/properties&amp;gt;
                            &amp;lt;/deployable&amp;gt;
                        &amp;lt;/deployables&amp;gt;
                    &amp;lt;/configuration&amp;gt;
                &amp;lt;/configuration&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;start-container&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;start&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                    &amp;lt;/execution&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;id&amp;gt;stop-container&amp;lt;/id&amp;gt;
                        &amp;lt;phase&amp;gt;post-integration-test&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;stop&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;selenium-maven-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;1.0&amp;lt;/version&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;phase&amp;gt;pre-integration-test&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;start-server&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;background&amp;gt;true&amp;lt;/background&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;executions&amp;gt;
                    &amp;lt;execution&amp;gt;
                        &amp;lt;phase&amp;gt;integration-test&amp;lt;/phase&amp;gt;
                        &amp;lt;goals&amp;gt;
                            &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;
                        &amp;lt;/goals&amp;gt;
                        &amp;lt;configuration&amp;gt;
                            &amp;lt;excludes&amp;gt;
                                &amp;lt;exclude&amp;gt;none&amp;lt;/exclude&amp;gt;
                            &amp;lt;/excludes&amp;gt;
                            &amp;lt;includes&amp;gt;
                                &amp;lt;include&amp;gt;**/*SeleniumTest.java&amp;lt;/include&amp;gt;
                            &amp;lt;/includes&amp;gt;
                            &amp;lt;systemProperties&amp;gt;
                                &amp;lt;property&amp;gt;
                                    &amp;lt;name&amp;gt;selenium.browser&amp;lt;/name&amp;gt;
                                    &amp;lt;value&amp;gt;${selenium.browser}&amp;lt;/value&amp;gt;
                                &amp;lt;/property&amp;gt;
                                &amp;lt;property&amp;gt;
                                    &amp;lt;name&amp;gt;cargo.port&amp;lt;/name&amp;gt;
                                    &amp;lt;value&amp;gt;${cargo.port}&amp;lt;/value&amp;gt;
                                &amp;lt;/property&amp;gt;
                            &amp;lt;/systemProperties&amp;gt;
                        &amp;lt;/configuration&amp;gt;
                    &amp;lt;/execution&amp;gt;
                &amp;lt;/executions&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
&amp;lt;/profile&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This profile is run by our Bamboo nightly tests with &lt;code&gt;mvn install -Pitest-bamboo&lt;/code&gt;. The 2nd profile I added doesn&apos;t install the project&apos;s WAR, but instead installs the two separate WARs. Running &lt;code&gt;mvn install -Pitest-bamboo,multiple-wars&lt;/code&gt; executes the Selenium tests against the multi-WAR distribution.
&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
&amp;lt;profile&amp;gt;
    &amp;lt;id&amp;gt;multiple-wars&amp;lt;/id&amp;gt;
    &amp;lt;activation&amp;gt;
        &amp;lt;activeByDefault&amp;gt;false&amp;lt;/activeByDefault&amp;gt;
    &amp;lt;/activation&amp;gt;
    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.cargo&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;cargo-maven2-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;${cargo.version}&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;configuration&amp;gt;
                        &amp;lt;home&amp;gt;${project.build.directory}/${cargo.container}/container&amp;lt;/home&amp;gt;
                        &amp;lt;properties&amp;gt;
                            &amp;lt;cargo.hostname&amp;gt;${cargo.host}&amp;lt;/cargo.hostname&amp;gt;
                            &amp;lt;cargo.servlet.port&amp;gt;${cargo.port}&amp;lt;/cargo.servlet.port&amp;gt;
                        &amp;lt;/properties&amp;gt;
                        &amp;lt;deployables&amp;gt;
                            &amp;lt;deployable&amp;gt;
                                &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
                                &amp;lt;artifactId&amp;gt;product-client&amp;lt;/artifactId&amp;gt;
                                &amp;lt;pingURL&amp;gt;http://${cargo.host}:${cargo.port}/product-client/index.html&amp;lt;/pingURL&amp;gt;
                                &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
                                &amp;lt;properties&amp;gt;
                                    &amp;lt;context&amp;gt;/product-client&amp;lt;/context&amp;gt;
                                &amp;lt;/properties&amp;gt;
                            &amp;lt;/deployable&amp;gt;
                            &amp;lt;deployable&amp;gt;
                                &amp;lt;groupId&amp;gt;com.company.app&amp;lt;/groupId&amp;gt;
                                &amp;lt;artifactId&amp;gt;product-services&amp;lt;/artifactId&amp;gt;
                                &amp;lt;pingURL&amp;gt;
                                    http://${cargo.host}:${cargo.port}/project-services/index.jspx
                                &amp;lt;/pingURL&amp;gt;
                                &amp;lt;type&amp;gt;war&amp;lt;/type&amp;gt;
                                &amp;lt;properties&amp;gt;
                                    &amp;lt;context&amp;gt;/product-services&amp;lt;/context&amp;gt;
                                &amp;lt;/properties&amp;gt;
                            &amp;lt;/deployable&amp;gt;
                        &amp;lt;/deployables&amp;gt;
                    &amp;lt;/configuration&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
&amp;lt;/profile&amp;gt;
&lt;/pre&gt;
&lt;p&gt;I won&apos;t be including any information on authoring Selenium tests because there&apos;s already many good references. I encourage you to checkout the following if you&apos;re looking for Selenium testing techniques.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/carlossg/appfuse-selenium&quot;&gt;Carlos Sanchez&apos;s Selenium Test Environment for AppFuse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.extjs.com/blog/2008/11/03/testing-ext-js-ext-gwt-applications-with-selenium/&quot;&gt;Testing Ext JS &amp;amp; Ext GWT Applications With Selenium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sonatype.com/people/2009/09/testing-nexus-with-selenium-a-lesson-in-complex-ui-testing-part-1/&quot;&gt;Testing Nexus with Selenium: A lesson in complex UI testing (Part 1)&lt;/a&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sonatype.com/people/2009/10/selenium-part-2/&quot;&gt;Testing Nexus with Selenium: A lesson in complex UI testing (Part 2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sonatype.com/people/2009/10/selenium-part-3/&quot;&gt;Testing Nexus with Selenium: A lesson in complex UI testing (Part 3)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br/&gt;
This article has shown you how I used Maven, war overlays and the UrlRewriteFilter to allow create different distributions of a SOFEA application. I&apos;m still not sure which packaging (1 WAR vs. 2) mechanism is best, but it&apos;s nice to know there&apos;s options. If you package and distribute SOFEA applications, I&apos;d love to hear about your experience in this area.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/how_to_use_gwt_2</guid>
    <title>How to use GWT 2.0 with Maven and Generate SOYC Reports</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/how_to_use_gwt_2</link>
        <pubDate>Thu, 25 Jun 2009 23:45:04 -0600</pubDate>
    <category>Java</category>
    <category>gwt-maven-plugin</category>
    <category>runasync</category>
    <category>maven</category>
    <category>soyc</category>
    <category>gwt</category>
            <description>One of the most interesting features coming in GWT 2.0 is &lt;a href=&quot;http://code.google.com/p/google-web-toolkit/wiki/CodeSplitting&quot;&gt;code splitting&lt;/a&gt; and the ability to use GWT.runAsync() to reduce the size of your application&apos;s initial download. This week, I learned how to use GWT 2.0 with my GWT 1.6/Maven project. Below are instructions on how to build and use the latest GWT with Maven.
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://code.google.com/webtoolkit/makinggwtbetter.html#compiling&quot;&gt;Checkout GWT and setup GWT_TOOLS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Set a GWT_VERSION environment variable to &lt;em&gt;2.0.0-SNAPSHOT&lt;/em&gt; (export GWT_VERSION=2.0.0-SNAPSHOT).&lt;/li&gt;
&lt;li&gt;Build GWT with the &lt;em&gt;ant&lt;/em&gt; command.&lt;/li&gt;
&lt;li&gt;After building completes, install the GWT artifacts into your local Maven repository using the following commands: 
&lt;pre style=&quot;margin-top: 5px&quot;&gt;mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-user -Dversion=2.0.0-SNAPSHOT \
-Dpackaging=jar -Dfile=build/lib/gwt-user.jar

mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-servlet -Dversion=2.0.0-SNAPSHOT \
-Dpackaging=jar -Dfile=build/lib/gwt-servlet.jar

mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-dev -Dversion=2.0.0-SNAPSHOT \
-Dclassifier=mac -Dpackaging=jar -Dfile=build/lib/gwt-dev-mac.jar

mkdir temp
tar -zxf build/dist/gwt-mac-2.0.0-SNAPSHOT.tar.gz -C temp
cd temp/gwt-mac-2.0.0-SNAPSHOT
zip -0 gwt-mac-2.0.0-SNAPSHOT.zip lib*.jnilib
cd ../..

mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-dev -Dversion=2.0.0-SNAPSHOT \
-Dclassifier=mac-libs -Dpackaging=zip \
-Dfile=temp/gwt-mac-2.0.0-SNAPSHOT/gwt-mac-2.0.0-SNAPSHOT.zip
&lt;/pre&gt;
&lt;div style=&quot;margin-bottom: 5px; text-align: right&quot;&gt;&lt;em&gt;Thanks to &lt;a href=&quot;http://groups.google.com/group/codehaus-mojo-gwt-maven-plugin-users/browse_thread/thread/83e860b1de4565f5&quot;&gt;Jason&lt;/a&gt; for his help with this script.&lt;/em&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Modify the pom.xml of your GWT project to use the the &lt;a href=&quot;http://mojo.codehaus.org/gwt-maven-plugin/&quot;&gt;gwt-maven-plugin&lt;/a&gt; from Codehaus. Of course, you&apos;ll need to modify the &amp;lt;runTarget&amp;gt; to fit your project.
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;gwt-maven-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;runTarget&amp;gt;org.appfuse.gwt.mvc.${entry.point}/${entry.point}.html&amp;lt;/runTarget&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;compile&amp;lt;/goal&amp;gt;
                &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Modify your dependencies to match the ones below. With the Codehaus plugin, dependencies are much more concise.
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.google.gwt&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;gwt-servlet&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${gwt.version}&amp;lt;/version&amp;gt;
    &amp;lt;scope&amp;gt;compile&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.google.gwt&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;gwt-user&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${gwt.version}&amp;lt;/version&amp;gt;
    &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Add &lt;em&gt;&amp;lt;gwt.version&gt;2.0.0-SNAPSHOT&amp;lt;/gwt.version&gt;&lt;/em&gt; to the properties section of your pom.xml.&lt;/li&gt;
&lt;li&gt;At this point, you should be able to compile your project with &lt;strong&gt;mvn gwt:compile&lt;/strong&gt; and run it in hosted mode using &lt;strong&gt;mvn gwt:run&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Generate SOYC Reports&lt;/strong&gt;&lt;br/&gt;
In Google&apos;s code splitting documentation, it mentions &lt;a href=&quot;http://code.google.com/p/google-web-toolkit/wiki/CodeSplitting#The_Story_of_Your_Compile_(SOYC)&quot;&gt;The Story of Your Compile (SOYC)&lt;/a&gt;. From the documentation:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
To obtain a SOYC report for your application, there are two steps necessary. First, add -soyc to the compilation options that are passed to the GWT compiler. This will cause the compiler to emit raw information about the compile to XML files in an -aux directory beside the rest of the compiled output. In that directory, you will see an XML file for each permutation and a manifest.xml file that describes the contents of all the others.
&lt;br/&gt;&lt;br/&gt;
The second step is to convert that raw information into viewable HTML. This is done with the SoycDashboard tool.
&lt;/p&gt;
&lt;p&gt;The first step is not currently possible with the gwt-maven-plugin, so I &lt;a href=&quot;http://jira.codehaus.org/browse/MGWT-92&quot;&gt;created a patch for it&lt;/a&gt;. 
&lt;/p&gt;
&lt;p style=&quot;margin-left: 20px; color: #666&quot;&gt;&lt;em&gt;
If you patch the gwt-maven-plugin and install it locally, make sure and change the version in your pom.xml to &lt;strong&gt;1.2-SNAPSHOT&lt;/strong&gt;.
&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To use the SoycDashboard tool, you&apos;ll need to install the gwt-soyc-vis.jar.
&lt;pre&gt;
mvn install:install-file -DgroupId=com.google.gwt \
-DartifactId=gwt-soyc-vis -Dversion=2.0.0-SNAPSHOT \
-Dpackaging=jar -Dfile=build/lib/gwt-soyc-vis.jar
&lt;/pre&gt;
&lt;p&gt;Now you can generate SOYC reports with &lt;strong&gt;mvn gwt:compile -Dgwt.compiler.soyc=true&lt;/strong&gt;. You can also add &amp;lt;soyc&amp;gt;true&amp;lt;/soyc&amp;gt; to the &amp;lt;configuration&amp;gt; section of the gwt-maven-plugin.&lt;/p&gt;
&lt;p&gt;The second step (converting the raw information into viewable HTML) is possible using &lt;em&gt;java&lt;/em&gt; from the command-line, or by using the &lt;a href=&quot;http://mojo.codehaus.org/exec-maven-plugin/&quot;&gt;exec-maven-plugin&lt;/a&gt;. Here&apos;s the (lengthy) command-line version:&lt;/p&gt;
&lt;pre&gt;java -Xmx1024m -cp /Users/mraible/.m2/repository/com/google/gwt/gwt-soyc/2.0.0-SNAPSHOT/gwt-soyc-2.0.0-SNAPSHOT.jar:/Users/mraible/.m2/repository/com/google/gwt/gwt-dev/2.0.0-SNAPSHOT/gwt-dev-2.0.0-SNAPSHOT-mac.jar com.google.gwt.soyc.SoycDashboard -resources ~/.m2/repository/com/google/gwt/gwt-soyc/2.0.0-SNAPSHOT/gwt-soyc-2.0.0-SNAPSHOT.jar -out target/soyc-report target/extra/org.appfuse.gwt.mvc.MVC/soycReport/stories0.xml.gz target/extra/org.appfuse.gwt.mvc.MVC/soycReport/dependencies0.xml.gz target/extra/org.appfuse.gwt.mvc.MVC/soycReport/splitPoints0.xml.gz&lt;/pre&gt;
&lt;p&gt;In this example, I&apos;m using the files from &lt;em&gt;stories0.xml.gz&lt;/em&gt;, &lt;em&gt;dependencies0.xml.gz&lt;/em&gt;, &lt;em&gt;splitPoints0.xml.gz&lt;/em&gt;. In the &lt;em&gt;soycReport&lt;/em&gt; output directory, there&apos;s 5 of each these files and I&apos;m not sure what the difference between reports is. Hopefully someone on the GWT team can elaborate. The exec-maven-plugin version is as follows:&lt;/p&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.codehaus.mojo&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;exec-maven-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.1&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;executable&amp;gt;java&amp;lt;/executable&amp;gt;
        &amp;lt;arguments&amp;gt;
            &amp;lt;argument&amp;gt;-cp&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;
                ${settings.localRepository}/com/google/gwt/gwt-soyc/2.0.0-SNAPSHOT/gwt-soyc-2.0.0-SNAPSHOT.jar:${settings.localRepository}/com/google/gwt/gwt-dev/2.0.0-SNAPSHOT/gwt-dev-2.0.0-SNAPSHOT-${platform}.jar
            &amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;com.google.gwt.soyc.SoycDashboard&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;-out&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;target/soyc-report&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;-resources&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;
                ${settings.localRepository}/com/google/gwt/gwt-soyc/2.0.0-SNAPSHOT/gwt-soyc-2.0.0-SNAPSHOT.jar
            &amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;${project.build.directory}/extra/org.appfuse.gwt.mvc.MVC/soycReport/stories0.xml.gz&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;${project.build.directory}/extra/org.appfuse.gwt.mvc.MVC/soycReport/dependencies0.xml.gz&amp;lt;/argument&amp;gt;
            &amp;lt;argument&amp;gt;${project.build.directory}/extra/org.appfuse.gwt.mvc.MVC/soycReport/splitPoints0.xml.gz&amp;lt;/argument&amp;gt;
        &amp;lt;/arguments&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;After configuring this plugin in your project, you should be able to run &lt;strong&gt;mvn gwt:compile exec:exec&lt;/strong&gt; and open the generated report (at &lt;em&gt;target/soyc-report/SoycDashboard-index.html&lt;/em&gt;). Currently, there doesn&apos;t seem to be much documentation on SOYC. &lt;a href=&quot;http://www.slideshare.net/fredsa/gwt-overview-and-feature-preview-sv-web-jug-june-16-2009&quot;&gt;Fred Sauer&apos;s recent presentation&lt;/a&gt; talks a bit about SOYC and GWT.runAsync(), but that&apos;s about it.&lt;/p&gt;
&lt;p&gt;To figure out how to use GWT 2.0 with Maven, I used my &lt;a href=&quot;http://raibledesigns.com/rd/entry/gxt_s_mvc_framework&quot;&gt;GWT MVC Example&lt;/a&gt; project. The first SOYC report I generated said the initial download was 108,967 KB. To integrate GWT.runAsync(), I modified all the project&apos;s controllers so their &lt;em&gt;handleEvent()&lt;/em&gt; methods changed from this:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public void handleEvent(AppEvent&lt;?&gt; event) {
    onViewHome(event);
}
&lt;/pre&gt;
&lt;p&gt;To this:&lt;/p&gt;
&lt;pre class=&quot;brush: java&quot;&gt;
public void handleEvent(final AppEvent&lt;?&gt; event) {
    GWT.runAsync(new RunAsyncCallback() {
        public void onFailure(Throwable throwable) {
            Window.alert(throwable.getMessage());
        }

        public void onSuccess() {
            onViewHome(event);
        }
    });
}

&lt;/pre&gt;&lt;p&gt;When I generated a new SOYC report, the initial download size was reduced to 56,718 KB. Furthermore, I was able to see that my &quot;Leftovers code&quot; consisted of 63,175 KB. I&apos;m sure there&apos;s better ways to split my project using GWT.runAsync(), but I&apos;m happy to see I was able to reduce the initial download by 50%. &lt;/p&gt;
&lt;p&gt;If you&apos;d like to try GWT 2.0, you can can &lt;a href=&quot;http://static.raibledesigns.com/downloads/gwt-mvc-1.1.zip&quot;&gt;download my gwt-mvc example project&lt;/a&gt;. To build/run this project, you&apos;ll need to 1) build and install GWT, 2) patch gwt-maven-plugin and 3) run &lt;strong&gt;mvn gwt:compile exec:exec&lt;/strong&gt; to generate the SOYC report. In an ideal world, the gwt-maven-plugin can be enhanced to generate the SOYC report (rather than using the exec-maven-plugin). In the meantime, I think it&apos;s pretty cool that you can try out GWT 2.0 features while they&apos;re still being developed.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/optimizing_a_gwt_application_with</guid>
    <title>Optimizing a GWT Application with Multiple EntryPoints</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/optimizing_a_gwt_application_with</link>
        <pubDate>Wed, 25 Mar 2009 16:00:37 -0600</pubDate>
    <category>Java</category>
    <category>gzip</category>
    <category>webframeworks</category>
    <category>gwt-maven</category>
    <category>optimization</category>
    <category>gwt</category>
    <category>entrypoint</category>
    <category>maven</category>
            <description>Building a GWT application is an easy way for Java Developers to write Ajax applications. However, it can be difficult to release a GWT application to production before it&apos;s finished. One of the most important things I&apos;ve learned in Software Development is to get a new application into production as soon as possible. Not only does getting it from dev &amp;rarr; qa &amp;rarr; prod verify your process works, it also can do a lot to test the viability of the new application.
&lt;/p&gt;
&lt;p&gt;One of the biggest issues with GWT applications is size. The project I&apos;m working on compiles Java to JavaScript and creates ~570K *.cache.html files (one for each modern browser). These files end up being around 180K gzipped. I believe this is an OK size for an entire application. However, if you&apos;re going to &lt;em&gt;release early, release often&lt;/em&gt; with GWT, chances are you&apos;ll just want to release one feature at a time. &lt;/p&gt;
&lt;p&gt;When the first feature was completed on my project, the *.cache.html files were around 300K. Rather than using branches to release to QA and UAT, bug fixes and new features were developed on trunk. Unfortunately, the QA and UAT process took several weeks longer than expected so by the time the feature was ready to release, the *.cache.html files had grown to around ~570K. The reason the file had grown so much was because it included all of the other features.&lt;/p&gt;
&lt;p&gt;Earlier this week, while running to a dentist appointment, I thought of a solution to this problem. The basic idea was to optimize the compilation process so only the to-be-released feature was included. Even better, the solution didn&apos;t require &lt;a href=&quot;http://raibledesigns.com/rd/entry/modularizing_gwt_applications_with_gwt&quot;&gt;more modularization&lt;/a&gt;. The results:&lt;/p&gt;
&lt;pre&gt;
Before: *.cache.html -&gt; 569K, gzipped 175K
After: *.cache.html -&gt; 314K, gzipped 100K
&lt;/pre&gt;
&lt;p&gt;According to my calculations, that&apos;s a 56% reduction in size. How did I do it?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Created a new &lt;code&gt;FeatureName.java&lt;/code&gt; EntryPoint with only the to-be-released features imported. &lt;/li&gt;
&lt;li&gt;Created a new &lt;code&gt;FeatureName.gwt.xml&lt;/code&gt; that references the new EntryPoint.&lt;/li&gt;
&lt;li&gt;Copied old (kitchen-sink) EntryPoint.html to &lt;code&gt;FeatureName.html&lt;/code&gt; and changed the reference to the nocache.js file.&lt;/li&gt;
&lt;li&gt;Created a Maven profile that allows using -PFeatureName to build a FeatureName-only module.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;One downside to doing things this way is it&apos;s possible to create a WAR that has the same name and different features. Surely the Maven Overlords would frown upon this. Since this is just a temporary solution to release features incrementally, I&apos;m not too worried about it. A possible workaround is to create different WAR names when a feature&apos;s profile is activated. I believe the true &quot;Maven way&quot; would be to make the &quot;kitchen sink&quot; application into a JAR and have several WAR modules with the different EntryPoints. Seems a bit complicated to me.
&lt;/p&gt;
&lt;p&gt;Other than this Maven publishing issue, the only other issue I can foresee is keeping the two EntryPoints and HTML files in synch. Then again, the separate files allow a feature to be customized for the release and can be deleted when its no longer needed.
&lt;/p&gt;
&lt;p&gt;What do you think? Do you know of a better way to compile a GWT application so it only contains certain features?</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/modularizing_gwt_applications_with_gwt</guid>
    <title>Modularizing GWT Applications with GWT-Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/modularizing_gwt_applications_with_gwt</link>
        <pubDate>Mon, 23 Mar 2009 10:36:08 -0600</pubDate>
    <category>Java</category>
    <category>gwt</category>
    <category>gwt-maven-plugin</category>
    <category>gwt-maven</category>
    <category>maven</category>
            <description>Last week, I spent some time modularizing the GWT application I&apos;m working on. By &lt;em&gt;modularizing&lt;/em&gt;, I mean splitting the code from one GWT module into a &quot;core&quot; and &quot;webapp&quot; module. The reason for doing this was so the &quot;core&quot; module could be used by another GWT application. Creating &lt;a href=&quot;http://code.google.com/docreader/#p=google-web-toolkit-doc-1-5&amp;s=google-web-toolkit-doc-1-5&amp;t=DevGuideModules&quot;&gt;GWT Modules&lt;/a&gt; is fairly straightforward, but it wasn&apos;t as intuitive as expected when using the &lt;a href=&quot;http://code.google.com/p/gwt-maven/&quot;&gt;gwt-maven-plugin&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;The hardest part of moving the code was figuring out how to run tests in the new &quot;core&quot; module. After getting it all working, it seems easy enough. Hopefully this post will make it easy for others. Here&apos;s the steps I&apos;d recommend:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Convert your GWT project into a multi-module project where you have a top-level pom.xml and two sub-modules (e.g. gwt-core and gwt-webapp).&lt;/li&gt;
&lt;li&gt;Do the normal single-to-multi-project Maven stuff like declaring the &amp;lt;parent&amp;gt; element in the modules and moving plugins/dependencies to the top-level pom.xml.&lt;/li&gt;
&lt;li&gt;Refactor your gwt-webapp project to push down all shared classes (and their tests) to gwt-core.&lt;/li&gt;
&lt;li&gt;In the gwt-core project, include *.xml and *.java in your JAR so GWT can extract/compile the source code when building gwt-webapp.
&lt;pre class=&quot;brush:xml&quot;&gt;
&amp;lt;resources&amp;gt;
    &amp;lt;resource&amp;gt;
        &amp;lt;directory&amp;gt;src/main/java&amp;lt;/directory&amp;gt;
        &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*.java&amp;lt;/include&amp;gt;
            &amp;lt;include&amp;gt;**/*.xml&amp;lt;/include&amp;gt;
        &amp;lt;/includes&amp;gt;
    &amp;lt;/resource&amp;gt;
&amp;lt;/resources&amp;gt;
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;gwt-core/src/main/java&lt;/code&gt;, create a &lt;code&gt;Core.gwt.xml&lt;/code&gt; that references the modules you&apos;d like to use in all your applications. For example:
&lt;pre class=&quot;brush:xml&quot;&gt;
&amp;lt;module&gt;
    &amp;lt;inherits name=&quot;com.google.gwt.user.User&quot;/&gt;
    &amp;lt;inherits name=&quot;com.google.gwt.i18n.I18N&quot;/&gt;
    &amp;lt;inherits name=&quot;com.extjs.gxt.ui.GXT&quot;/&gt;
    &amp;lt;inherits name=&quot;pl.rmalinowski.gwt2swf.GWT2SWF&quot;/&gt;
&amp;lt;/module&gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Now the tricky part begins, mostly because of how the gwt-maven plugin currently works. In &lt;code&gt;src/test/java&lt;/code&gt;, create a &lt;code&gt;NoOpEntryPoint.gwt.xml&lt;/code&gt; that inherits your Core module and defines an EntryPoint.
&lt;pre class=&quot;brush:xml&quot;&gt;
&amp;lt;module&amp;gt;
    &amp;lt;inherits name=&quot;com.company.app.Core&quot;/&amp;gt;
    &amp;lt;entry-point class=&quot;com.company.app.NoOpEntryPoint&quot;/&amp;gt;
&amp;lt;/module&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;NoOpEntryPoint.java&lt;/code&gt; class in the same directory as &lt;code&gt;NoOpEntryPoint.gwt.xml&lt;/code&gt;.&lt;/pre&gt;
&lt;pre class=&quot;brush:java&quot;&gt;
public class NoOpEntryPoint implements EntryPoint {
    
    public void onModuleLoad() {
        // do nothing
    }
}
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;In any class that extends GWTTestCase (I usually create a parent class for all tests), reference the NoOpEntryPoint in the &lt;code&gt;getModuleName()&lt;/code&gt; method.
&lt;pre class=&quot;brush:java&quot;&gt;
    @Override
    public String getModuleName() {
        return &quot;com.company.app.NoOpEntryPoint&quot;;
    }
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Lastly, in the gwt-maven plugin&apos;s configuration (in gwt-core/pom.xml), reference the NoOpEntryPoint in &amp;lt;compileTargets&amp;gt;, a non-existent file in &amp;lt;runTarget&amp;gt; and only the &quot;test&quot; goal in the executions.
&lt;pre class=&quot;brush:xml&quot;&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;com.totsp.gwt&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-googlewebtoolkit2-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.0-beta26&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;compileTargets&amp;gt;
            &amp;lt;value&amp;gt;com.company.app.NoOpEntryPoint&amp;lt;/value&amp;gt;
        &amp;lt;/compileTargets&amp;gt;
        &amp;lt;runTarget&amp;gt;com.company.app.NoOpEntryPoint/doesntexist.html&amp;lt;/runTarget&amp;gt;
        &amp;lt;logLevel&amp;gt;INFO&amp;lt;/logLevel&amp;gt;
        &amp;lt;style&amp;gt;OBF&amp;lt;/style&amp;gt;
        &amp;lt;noServer&amp;gt;false&amp;lt;/noServer&amp;gt;
        &amp;lt;extraJvmArgs&amp;gt;-Xmx512m&amp;lt;/extraJvmArgs&amp;gt;
        &amp;lt;gwtVersion&amp;gt;${gwtVersion}&amp;lt;/gwtVersion&amp;gt;
        &amp;lt;testFilter&amp;gt;*GwtTestSuite.java&amp;lt;/testFilter&amp;gt;
        &amp;lt;testSkip&amp;gt;${skipTests}&amp;lt;/testSkip&amp;gt;
    &amp;lt;/configuration&amp;gt;
    &amp;lt;executions&amp;gt;
        &amp;lt;execution&amp;gt;
            &amp;lt;goals&amp;gt;
                &amp;lt;goal&amp;gt;test&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
        &amp;lt;/execution&amp;gt;
    &amp;lt;/executions&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The results of modularizing your application are beneficial (shared code) and detrimental (you have to &lt;code&gt;mvn install&lt;/code&gt; gwt-core whenever you make changes in shared classes). If you know of a way to configure the gwt-maven plugin to read sources from both gwt-core and gwt-webapp in hosted mode, I&apos;d love to hear about it. </description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/nexus_is_a_kick_ass</guid>
    <title>Nexus is a kick-ass Repository Manager</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/nexus_is_a_kick_ass</link>
        <pubDate>Thu, 5 Mar 2009 23:59:02 -0700</pubDate>
    <category>Java</category>
    <category>nexus</category>
    <category>sonatype</category>
    <category>repositorymanager</category>
    <category>maven</category>
            <description>I started my &lt;a href=&quot;http://raibledesigns.com/rd/entry/what_s_next&quot;&gt;current gig&lt;/a&gt; at the end of last year. I&apos;ve been enjoying the work and especially the project infrastructure we&apos;ve been using. We&apos;re using the usual suspects: JIRA, Confluence, Hudson and Subversion. We&apos;re also using a couple new ones, namely &lt;a href=&quot;http://www.sventon.org/&quot;&gt;sventon&lt;/a&gt; and &lt;a href=&quot;http://nexus.sonatype.org/&quot;&gt;Nexus&lt;/a&gt;. For building, we&apos;re using Maven and Ivy (as a Grails plugin). 
&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;http://farm4.static.flickr.com/3626/3331881717_9cc73cf048_o.png&quot; rel=&quot;lightbox[nexus]&quot; title=&quot;Nexus&quot;&gt;&lt;img src=&quot;//farm4.static.flickr.com/3626/3331881717_0a224b75f6_m.jpg&quot; width=&quot;157&quot; height=&quot;240&quot; alt=&quot;Nexus&quot; class=&quot;picture&quot; style=&quot;border: 0&quot;/&gt;&lt;/a&gt;
I&apos;m writing this post to talk about Nexus and how much I&apos;ve enjoyed using it. I like Nexus for two reasons: it&apos;s &lt;a href=&quot;http://oss.sonatype.org/index.html&quot;&gt;aesthetically pleasing&lt;/a&gt; and it&apos;s &lt;a href=&quot;http://www.sonatype.com/books/nexus-book/reference/index.html&quot;&gt;well-documented&lt;/a&gt;. Another reason I really dig it is because I haven&apos;t had to touch it since I first configured it. Software that just keeps on humming is always fun to work with.
&lt;/p&gt;
&lt;p&gt;Initially, I remember having &lt;a href=&quot;http://nexus.sonatype.org/mailing-list-user-archives.html&quot;&gt;some issues&lt;/a&gt; setting up repositories. I also remember solving them after learning &lt;a href=&quot;http://www.sonatype.com/books/nexus-book/reference/config.html#config-sect-managing-groups&quot;&gt;how groups work&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;In addition to on-the-job, I&apos;ve started to use Nexus more and more in my open source life. With the help of &lt;a href=&quot;http://www.sonatype.com/people/author/jason/&quot;&gt;Jason van Zyl&lt;/a&gt;, I recently moved AppFuse&apos;s repository to Sonatype&apos;s &lt;a href=&quot;http://oss.sonatype.org&quot;&gt;oss.sonatype.org&lt;/a&gt;. I also noticed there&apos;s &lt;a href=&quot;https://repository.apache.org/index.html&quot;&gt;a Nexus instance for Apache projects&lt;/a&gt;. If that&apos;s not enough, you can &lt;a href=&quot;http://www.sonatype.com/products/nexus/oss_license_request&quot;&gt;get Nexus Pro free&lt;/a&gt; if you&apos;re an open source project.
&lt;/p&gt;
&lt;p&gt;Personally, the open source version of Nexus seems good enough for me. While the &lt;a href=&quot;http://vimeo.com/2985451&quot;&gt;Staging Suite&lt;/a&gt; looks nice, I think it&apos;s possible to do a lot of similar things with good communication. After all, it&apos;s not going to free you from having to wrestle with the &lt;a href=&quot;http://maven.apache.org/plugins/maven-release-plugin/&quot;&gt;maven-release-plugin&lt;/a&gt;. 
&lt;/p&gt;
&lt;p&gt;Next week, I&apos;m helping to polish and document our entire release process (from dev &amp;rarr; qa &amp;rarr; production). If you have any advice on how to best perform releases with Maven, Grails and/or Nexus, I&apos;d love to hear about it. My goal is extreme efficiency so releases can be done very quickly and with minimal effort.

</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/gwttestsuite_makes_builds_faster_but</guid>
    <title>GWTTestSuite makes builds faster, but requires JUnit 4.1</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/gwttestsuite_makes_builds_faster_but</link>
        <pubDate>Fri, 27 Feb 2009 11:58:12 -0700</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>junit</category>
    <category>gwt</category>
    <category>gwt-maven</category>
    <category>hudson</category>
    <category>gwttestsuite</category>
            <description>Earlier this week, I spent some time implementing &lt;a href=&quot;http://google-web-toolkit.googlecode.com/svn/javadoc/1.5/com/google/gwt/junit/tools/GWTTestSuite.html&quot;&gt;GWTTestSuite&lt;/a&gt; to speed up my project&apos;s build process. In Hudson, the project was taking around 15 minutes to build, locally it was only taking 5 minutes for &lt;em&gt;mvn test&lt;/em&gt;. 
In IDEA, I could run all the tests in under a minute. While 15 minutes isn&apos;t a long time for a build to execute, a co-worker expressed some concern:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Does Maven have to run GWT test and individual Java processes? (See target/gwtTest/*.sh) This arrangement and the overhead of JVM launches is another reason why builds take so long. As we add more GWT tests we are going to test that LinkedIn record for the slowest build ever.
&lt;/p&gt;
&lt;p&gt;
After this comment, I started looking into GWTTestSuite using &lt;a href=&quot;http://development.lombardi.com/?p=409&quot;&gt;Olivier Modica&apos;s blog entry&lt;/a&gt; as a guide. It was very easy to get things working in IDEA. However, when I&apos;d run &lt;em&gt;mvn test&lt;/em&gt;, I&apos;d get the following error:
&lt;/p&gt;
&lt;pre&gt;
Error: java.lang.ClassCastException
&lt;/pre&gt;
&lt;p&gt;No line numbers. No class information. Zilch. After comparing my project&apos;s pom.xml with the one from the default &lt;a href=&quot;http://gwt-maven.googlecode.com/svn/docs/maven-googlewebtoolkit2-plugin/archetype.html&quot;&gt;gwt-maven archetype&lt;/a&gt;, I noticed the default used JUnit 4.1, while I had the latest-and-supposedly-greatest JUnit 4.4. Reverting to JUnit 4.1 fixed the problem. Now Hudson takes 3:15 to execute the build instead of 15 minutes.
&lt;/p&gt;
&lt;p&gt;
The reason for this blog post is this doesn&apos;t seem to be documented anywhere. Hopefully other developers will find this entry when googling for this issue.&lt;/p&gt;
&lt;p&gt;Related to making GWT faster, I also added the following line to my Application.gwt.xml file:
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;set-property name=&quot;user.agent&quot; value=&quot;safari&quot; /&gt;
&lt;/pre&gt; 
&lt;p&gt;This dropped the &lt;code&gt;gwt:compile&lt;/code&gt; time from 1 minute to 25 seconds. As &lt;a href=&quot;http://code.google.com/p/google-web-toolkit-doc-1-5/wiki/FAQ_CompileOnePermutation&quot;&gt;explained in the documentation&lt;/a&gt;, you can use the &quot;user.agent&quot; setting to only generate one JS file for your app instead of 4. The strange thing about adding this setting was I pretty much forgot about it since everything seemed to work fine on both Safari and Firefox. When I started testing things in IE6, I started seeing a lot of JavaScript errors. After debugging for an hour or so, I realized this setting was there, removed it, and everything started working great in all browsers.
&lt;/p&gt;
&lt;p&gt;Now if I could just figure out how to use safari-only for development, but remove the line when building the WAR. Suggestions welcome.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/enhancing_your_gwt_application_with</guid>
    <title>Enhancing your GWT Application with the UrlRewriteFilter</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/enhancing_your_gwt_application_with</link>
        <pubDate>Mon, 23 Feb 2009 17:02:29 -0700</pubDate>
    <category>Java</category>
    <category>gwt-maven-plugin</category>
    <category>maven</category>
    <category>gwt</category>
    <category>urlrewritefilter</category>
            <description>Last week, I spent some time trying to &lt;a href=&quot;http://code.google.com/p/google-web-toolkit-doc-1-4/wiki/FAQ_ChangeLocationGWTApplicationFiles&quot;&gt;change the location of my cache/nocache HTML files&lt;/a&gt; in my GWT project. I started the project with the &lt;a href=&quot;http://gwt-maven.googlecode.com/svn/docs/maven-googlewebtoolkit2-plugin/archetype.html&quot;&gt;gwt-maven-plugin&apos;s archetype&lt;/a&gt;. The &lt;a href=&quot;http://groups.google.com/group/gwt-maven/browse_thread/thread/a46f540ca823e3d3&quot;&gt;message&lt;/a&gt; I posted to the gwt-maven Google Group is below.&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Rather than having my application&apos;s HTML file in
src/main/java/com/mycompany/Application.html, I&apos;d like to move it to
src/main/webapp/index.html. I tried copying the HTML and adding the
following to my index.html, but no dice:
&lt;br/&gt;&lt;br/&gt;
&amp;lt;meta name=&quot;gwt:module&quot; content=&quot;com.mycompany.Application&quot;/&gt;
&lt;br/&gt;&lt;br/&gt;
Is this possible with the gwt-maven-plugin? I&apos;d like to have my main
HTML and CSS at the root of my application.
&lt;/p&gt;
&lt;p&gt;
The good news is I figured out a solution using the &lt;a href=&quot;http://tuckey.org/urlrewrite/&quot;&gt;UrlRewriteFilter&lt;/a&gt; that 1) allows hosted mode to work as usual and 2) allows your app to be served up from the root URL (/ instead of /com.company.Module/Application.html). Here&apos;s the urlrewrite.xml that makes it all possible.&lt;/p&gt;
&lt;pre&gt;
&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
&amp;lt;!DOCENGINE urlrewrite PUBLIC &quot;-//tuckey.org//DTD UrlRewrite 3.0//EN&quot;
        &quot;http://tuckey.org/res/dtds/urlrewrite3.0.dtd&quot;&amp;gt;

&amp;lt;urlrewrite&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;^/$&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot; last=&quot;true&quot;&amp;gt;/com.mycompany.app.Application/Application.html&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;/index.html&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot; last=&quot;true&quot;&amp;gt;/com.mycompany.app.Application/Application.html&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
    &amp;lt;-- This last rule is necessary for JS and CSS files --&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;^/(.*)\.(.*)$&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot;&amp;gt;/com.mycompany.app.Application/$1.$2&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
&amp;lt;/urlrewrite&amp;gt;
&lt;/pre&gt;
&lt;p&gt; 
If you&apos;re using the gwt-maven plugin, this file goes in &lt;code&gt;src/main/webapp/WEB-INF&lt;/code&gt;. In addition, you&apos;ll need to add the following to your web.xml.
&lt;/p&gt;
&lt;pre&gt;
    &amp;lt;filter&amp;gt;
        &amp;lt;filter-name&amp;gt;rewriteFilter&amp;lt;/filter-name&amp;gt;
        &amp;lt;filter-class&amp;gt;org.tuckey.web.filters.urlrewrite.UrlRewriteFilter&amp;lt;/filter-class&amp;gt;
    &amp;lt;/filter&amp;gt;

    &amp;lt;filter-mapping&amp;gt;
        &amp;lt;filter-name&amp;gt;rewriteFilter&amp;lt;/filter-name&amp;gt;
        &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;
    &amp;lt;/filter-mapping&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Finally, add the UrlRewriteFilter dependency in your pom.xml:
&lt;/p&gt;
&lt;pre&gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.tuckey&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;urlrewritefilter&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;3.1.0&amp;lt;/version&amp;gt;
    &amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Please let me know if you have any questions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&quot;http://www.nofluffjuststuff.com/conference/speaker/jeff_genender.html&quot;&gt;Jeff&lt;/a&gt; posted an &lt;a href=&quot;http://groups.google.com/group/gwt-maven/msg/28146682e6ab510d&quot;&gt;alternative configuration&lt;/a&gt; that allows you to eliminate the last rule in urlrewrite.xml, as well as use the beloved &lt;strong&gt;mvn jetty:run&lt;/strong&gt; command. To use cleaner WAR packaging and the Jetty plugin, add the following to your pom.xml:
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-war-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;webappDirectory&amp;gt;
            ${project.build.directory}/${project.build.finalName}/com.mycompany.app.Application
        &amp;lt;/webappDirectory&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&amp;lt;plugin&amp;gt;
    &amp;lt;groupId&amp;gt;org.mortbay.jetty&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;maven-jetty-plugin&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;6.1.14&amp;lt;/version&amp;gt;
    &amp;lt;configuration&amp;gt;
        &amp;lt;webAppConfig&amp;gt;
            &amp;lt;contextPath&amp;gt;/&amp;lt;/contextPath&amp;gt;
            &amp;lt;baseResource implementation=&quot;org.mortbay.resource.ResourceCollection&quot;&amp;gt;
                &amp;lt;resourcesAsCSV&amp;gt;
                    ${basedir}/src/main/webapp,
                    ${project.build.directory}/${project.build.finalName}/com.mycompany.app.Application
                &amp;lt;/resourcesAsCSV&amp;gt;
            &amp;lt;/baseResource&amp;gt;
        &amp;lt;/webAppConfig&amp;gt;
        &amp;lt;scanIntervalSeconds&amp;gt;3&amp;lt;/scanIntervalSeconds&amp;gt;
        &amp;lt;scanTargets&amp;gt;
            &amp;lt;scanTarget&amp;gt;${basedir}/src/main/resources&amp;lt;/scanTarget&amp;gt;
            &amp;lt;scanTarget&amp;gt;${basedir}/src/main/webapp/WEB-INF&amp;lt;/scanTarget&amp;gt;
            &amp;lt;scanTarget&amp;gt;
                ${project.build.directory}/${project.build.finalName}/com.mycompany.app.Application
            &amp;lt;/scanTarget&amp;gt;
        &amp;lt;/scanTargets&amp;gt;
    &amp;lt;/configuration&amp;gt;
&amp;lt;/plugin&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Then you can trim your urlrewrite.xml down to:
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;urlrewrite&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;^/$&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot; last=&quot;true&quot;&amp;gt;/Application.html&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
    &amp;lt;rule&amp;gt;
        &amp;lt;from&amp;gt;/index.html&amp;lt;/from&amp;gt;
        &amp;lt;to type=&quot;forward&quot; last=&quot;true&quot;&amp;gt;/Application.html&amp;lt;/to&amp;gt;
    &amp;lt;/rule&amp;gt;
&amp;lt;/urlrewrite&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Of course, you could also change the welcome-file in your web.xml or use index.html and the &amp;lt;meta http-equiv=&quot;REFRESH&quot;&amp;gt; option. Personally, I have so much affection for the UrlRewriteFilter that I like having it in my project. I&apos;m sure I&apos;ll need it someday.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks Jeff!&lt;/em&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_light_converted_to_maven</guid>
    <title>AppFuse Light converted to Maven modules, upgraded to Tapestry 5 and Stripes 1.5</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_light_converted_to_maven</link>
        <pubDate>Sat, 20 Dec 2008 18:42:03 -0700</pubDate>
    <category>Java</category>
    <category>stripes</category>
    <category>jsf</category>
    <category>maven</category>
    <category>appfuselight</category>
    <category>struts2</category>
    <category>tapestry</category>
    <category>tapestry5</category>
    <category>appfuse</category>
            <description>This past week, I stayed up a couple of late nights to do some of the AppFuse Light work I &lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_light_appfuse_maven_archetypes&quot;&gt;wrote about in October&lt;/a&gt;. I converted all web frameworks to Maven modules, as well as made them inherit from the &lt;a href=&quot;http://static.appfuse.org/appfuse-web/index.html&quot;&gt;appfuse-web&lt;/a&gt; project. Below is what the new module structure looks like:&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;//farm4.static.flickr.com/3079/3124113000_904d35252b_o.png&quot; width=&quot;234&quot; height=&quot;181&quot; alt=&quot;New AppFuse Light Modules&quot; /&gt;&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;At this point, the project is ready to import into AppFuse&apos;s SVN project. Here&apos;s a list of other changes I made:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Modules now depend on AppFuse&apos;s backend and allow you to use Hibernate, JPA or iBATIS as the persistence framework. Implementations for Spring JDBC, OJB and JDO have been removed.&lt;/li&gt;
&lt;li&gt;Upgraded to &lt;a href=&quot;http://jwebunit.sourceforge.net/&quot;&gt;JWebUnit 2.1&lt;/a&gt;, which now uses &lt;a href=&quot;http://jwebunit.sourceforge.net/jwebunit-htmlunit-plugin/index.html&quot;&gt;HtmlUnit&lt;/a&gt; under the hood and has much better JavaScript support. It also has &lt;a href=&quot;http://jwebunit.sourceforge.net/jwebunit-selenium-plugin/index.html&quot;&gt;Selenium support&lt;/a&gt;, but I&apos;ve yet to try it.
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/ajaxified_body&quot;&gt;Ajaxified Body&lt;/a&gt; integrated into all frameworks. You can easily turn it off by modifying the global.js file.&lt;/li&gt;
&lt;li&gt;Prototype and Scriptaculous loaded from &lt;a href=&quot;http://code.google.com/apis/ajaxlibs/&quot;&gt;Google&apos;s Ajax Libraries CDN&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Upgraded to &lt;a href=&quot;http://java.dzone.com/announcements/apache-tapestry-50-final-relea&quot;&gt;Tapestry 5&lt;/a&gt;. Mad props to Serge Eby and his &lt;a href=&quot;http://code.google.com/p/tapestry5-appfuse/&quot;&gt;tapestry5-appfuse&lt;/a&gt; project for showing me how to do this. Serge &lt;a href=&quot;http://www.nabble.com/Welcome-to-the-AppFuse-Project!-td20966043s2369.html&quot;&gt;became a committer on AppFuse&lt;/a&gt; recently, so hopefully we&apos;ll continue to see great things from the Tapestry 5 support. I really like the clean URLs and minimum configuration required in Tapestry 5. It&apos;s testing framework is nice too, but &lt;a href=&quot;http://www.nabble.com/-T5--Testing-Pages-with-injected-Spring-beans-tt21057429.html&quot;&gt;I believe it could be improved&lt;/a&gt;.
&lt;li&gt;Upgraded to &lt;a href=&quot;http://greggbolinger.blogspot.com/2008/01/stripes-15-feature-general-improvements.html&quot;&gt;Stripes 1.5&lt;/a&gt;. This was easy and painless. I&apos;m definitely a fan of Stripes and look forward to reading the &lt;a href=&quot;http://www.pragprog.com/titles/fdstr/stripes&quot;&gt;Stripes book&lt;/a&gt; on my bookshelf.&lt;/li&gt;
&lt;li&gt;Dropped support for: Struts 1.x, WebWork, Spring MVC + Velocity.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;If you want to try any of these applications, you can create archetypes using the following commands:&lt;/p&gt;
&lt;pre&gt;
svn co https://appfuse-light.dev.java.net/svn/appfuse-light/trunk appfuse-light
cd appfuse-light/&lt;i&gt;preferred-web-framework&lt;/i&gt;
mvn archetype:create-from-project
cd target/generated-sources/archetype
mvn install
cd ~/dev
mvn archetype:generate # The new archetype should show up as an option
&lt;/pre&gt;
&lt;p&gt;Next steps include figuring out a way to flatten the inherited dependencies and plugins so &lt;em&gt;archetype:create-from-project&lt;/em&gt; can create truly standalone projects. Please let me know if you have any questions.

&lt;/pre&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/free_maven_training_in_new</guid>
    <title>Free Maven Training in New Orleans on Election Day</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/free_maven_training_in_new</link>
        <pubDate>Wed, 29 Oct 2008 21:55:45 -0600</pubDate>
    <category>Java</category>
    <category>nexus</category>
    <category>neworleans</category>
    <category>hudson</category>
    <category>m2eclipse</category>
    <category>maven</category>
            <description>Last week, I attended a talk by Jason van Zyl on &lt;a href=&quot;http://raibledesigns.com/rd/entry/comprehensive_project_intelligence_with_jason&quot;&gt;Comprehensive Project Intelligence&lt;/a&gt;. This talk contained a good overview of some Maven goodies that Jason&apos;s company has been working on - namely better repository management (Nexus), better Eclipse support (m2eclipse) and improving an &lt;a href=&quot;http://hudson.dev.java.net&quot;&gt;awesome CI server&lt;/a&gt; (we use Hudson heavily at LinkedIn). 
&lt;/p&gt;

&lt;div style=&quot;float:right;display: inline&quot;&gt;
&lt;a href=&quot;http://flickr.com/photos/toshio1/2008116038/&quot; title=&quot;Colorful New Orleans by * Toshio *&quot;&gt;&lt;img src=&quot;//farm3.static.flickr.com/2373/2008116038_d44235cffd_m.jpg&quot; alt=&quot;Colorful New Orleans&quot; width=&quot;240&quot; height=&quot;168&quot; class=&quot;picture&quot; style=&quot;margin-bottom: 0&quot;/&gt;&lt;/a&gt;&lt;div style=&quot;text-align: center&quot;&gt;Photo by Toshio&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
It looks like Jason is going to be doing a &lt;a href=&quot;http://blogs.sonatype.com/people/jvanzyl/2008/10/28/sonatype-free-maven-m2eclipse-nexus-hudson-training-in-new-orleans/&quot;&gt;similar session&lt;/a&gt; in a full-day format at ApacheCon next week. The good news is it&apos;s &lt;em&gt;free&lt;/em&gt;, the bad news is you have to be in New Orleans. Hopefully Jason and team will post their slides from this event and we can all learn how to use Maven more effectively.&lt;/p&gt;
&lt;p&gt;In other Maven-related news, I hope to complete AppFuse 2.1 around the same time as Spring 3.0 (early next year). As part of that release, I hope to start using Nexus for &lt;a href=&quot;http://static.appfuse.org/repository&quot;&gt;AppFuse&apos;s repository&lt;/a&gt; as well as &lt;a href=&quot;http://raibledesigns.com/rd/entry/appfuse_light_appfuse_maven_archetypes&quot;&gt;restructure its archetypes&lt;/a&gt; to allow using m2eclipse (with WTP) more effectively.
</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/appfuse_light_appfuse_maven_archetypes</guid>
    <title>AppFuse Light &#187; AppFuse, Maven Archetypes and Shared Web Assets</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/appfuse_light_appfuse_maven_archetypes</link>
        <pubDate>Wed, 29 Oct 2008 02:18:59 -0600</pubDate>
    <category>Java</category>
    <category>archetypes</category>
    <category>appfuse</category>
    <category>appfuselight</category>
    <category>svn</category>
    <category>maven</category>
    <category>architecture</category>
            <description>Last night, I stayed up into the wee hours of the morning working on something I&apos;ve been wanting to do for a long time. It wasn&apos;t until I was &lt;a href=&quot;http://raibledesigns.com/rd/entry/great_weekend_in_montana&quot;&gt;trouncing around the woods&lt;/a&gt; in Montana that I realized how easy it would be. The &lt;em&gt;something I&apos;ve wanted to do&lt;/em&gt; was to modify AppFuse Light to use AppFuse&apos;s core modules (service and dao). It only took me a few hours to make it happen and it inspired additional ideas. 
&lt;/p&gt;
&lt;p&gt;
I believe the major mistake we made in AppFuse 2.x was making it easy for user&apos;s to upgrade their applications. We currently use the &lt;a href=&quot;http://maven.apache.org/plugins/maven-war-plugin/&quot;&gt;maven-war-plugin&lt;/a&gt; and our own &lt;a href=&quot;http://static.appfuse.org/maven-warpath-plugin&quot;&gt;maven-warpath-plugin&lt;/a&gt; to make it possible to include AppFuse classes and assets in your project. You can easily &lt;a href=&quot;http://static.appfuse.org/movies/2.0/helloworld.mov&quot;&gt;start a new project&lt;/a&gt; w/o having a whole bunch of files in your project. The problem is, you can&apos;t easily use &quot;mvn jetty:run&quot; to work on your project. Of course, you can use &quot;mvn appfuse:full-source&quot; to solve this, but I&apos;m starting to think more and more that &quot;full-source&quot; should be the default. This is what we did in 1.x and it seems to be the more natural pattern for folks using AppFuse.
&lt;/p&gt;
&lt;p&gt;That hard part about moving to &quot;full-source&quot; by default is coming up with a way to share common assets and classes among wars and war projects. Sure, I can copy all the shared images, css and js
into each project - but that could become a maintenance nightmare. Subversion 1.5 with relative svn:externals might solve this, but it still seems kinda hacky. I don&apos;t want to use the maven-war-plugin because the overlay is kinda hokey and I think it&apos;s easier for users to understand when everything
is in their project.
 AppFuse&apos;s current directory structure in SVN looks as follows. I&apos;ve added indicators of what is in each directory.&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;
&lt;img src=&quot;//farm4.static.flickr.com/3231/2982950627_d846cda59b_o.png&quot; width=&quot;480&quot; height=&quot;148&quot; alt=&quot;AppFuse Web SVN&quot;/&gt;
&lt;/p&gt;
&lt;p&gt;Rather than using AppFuse&apos;s current (manual) archetype-creation process, I&apos;d like to move to a more automated creation process using the maven-archetype-plugin&apos;s &lt;a href=&quot;http://maven.apache.org/plugins/maven-archetype-plugin/create-from-project-mojo.html&quot;&gt;create-from-project&lt;/a&gt; feature. I&apos;d like to figure out a way where I can have the source code and assets from web/common included in each of the other web/* projects (both when using &quot;jetty:run&quot; and &quot;archetype:create-from-project&quot;). One idea I thought of is to make
Jetty/Maven aware of multiple src/war directories for &quot;jetty:run&quot; and &quot;package&quot; and then
somehow hook into the archetype plugin at creation time to pull in the
shared resources. I don&apos;t know if something like this is possible. If you know of a good solution to this &lt;em&gt;shared web assets&lt;/em&gt; issue, I&apos;d love to hear about it.
&lt;/p&gt;
&lt;p&gt;Back to AppFuse Light. If I can figure out how to solve shared resources in web modules, I can use this in AppFuse Light to move to a modular SVN structure vs. its current &quot;use Ant to create different combinations&quot; setup. If a modular structure (like appfuse/web/*) is possible for AppFuse Light, I believe it makes sense to move its source into AppFuse&apos;s SVN repository. Below is how the directory structure might look after this move.
&lt;/p&gt;
&lt;p style=&quot;text-align: center&quot;&gt;&lt;img src=&quot;//farm4.static.flickr.com/3165/2982969199_28fd1eefe4_o.png&quot; width=&quot;202&quot; height=&quot;181&quot; alt=&quot;AppFuse Light &#187; AppFuse&quot;/&gt;&lt;/p&gt;
&lt;p&gt;With this addition and &quot;archetype:create-from-project&quot;, we should be able to create all the &lt;em&gt;basic&lt;/em&gt; and &lt;em&gt;light&lt;/em&gt; archetypes automatically. We&apos;ll probably still need a manual archetype-creation process for modular archetypes, but I&apos;m OK with that.
&lt;/p&gt;
&lt;p&gt;The last thing I&apos;m struggling with is figuring out the best way to create archetypes for something like AppFuse. In the past, we&apos;ve used dependencies to allow users to inherit dependencies and their versions. This works, but it results in a lot of duplicate XML (in projects and archetypes) for developers. Last night, I tried using a parent project instead of dependencies and it seems to work much better. Not only do you inherit dependencies, but you also inherit plugins, profiles and properties. If you inherit, you can override, which is slick.
&lt;/p&gt;
&lt;p&gt;If you&apos;re an AppFuse user, how would you feel about having an AppFuse module as your project&apos;s parent? Would you prefer that, dependencies on AppFuse or full-source with no dependencies on AppFuse? Regardless of parent vs. dependencies, I think running &quot;appfuse:full-source&quot; should allow you to de-couple your project from AppFuse.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/colorado_software_summit_2008_wrapup</guid>
    <title>Colorado Software Summit 2008 Wrapup</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/colorado_software_summit_2008_wrapup</link>
        <pubDate>Tue, 28 Oct 2008 23:03:23 -0600</pubDate>
    <category>Java</category>
    <category>ajax</category>
    <category>maven</category>
    <category>softwaresummit</category>
    <category>spring</category>
    <category>rest</category>
    <category>java</category>
    <category>appcelerator</category>
    <category>camel</category>
            <description>&lt;a title=&quot;Snowman in Keystone&quot; href=&quot;http://blog.linkedin.com/blog/2008/10/colorado-softwa.html&quot;&gt;&lt;img alt=&quot;Snowman in Keystone&quot; src=&quot;//farm4.static.flickr.com/3057/2980923121_f44dd0dc42_t.jpg&quot; class=&quot;picture&quot; height=&quot;75&quot; width=&quot;100&quot;&gt;&lt;/a&gt;

Last week, I attended the Colorado Software Summit in Keystone and had a great time. Not only was the weather beautiful and the food delicious, the sessions I attended were awesome. If you ever get a chance to go to this conference, I highly recommend it. It&apos;s like being on vacation and learning with a bunch of old friends.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.linkedin.com/in/yan&quot;&gt;Yan Pujante&lt;/a&gt; also attended this conference and documents his experience, photography and presentations in &lt;a href=&quot;http://blog.linkedin.com/blog/2008/10/colorado-softwa.html&quot;&gt;Colorado Software Summit 2008&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;Below is a list of my entries for all the sessions I attended.&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/building_linkedin_s_next_generation&quot;&gt;Building LinkedIn&apos;s Next Generation Architecture with OSGi by Yan Pujante&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/comprehensive_project_intelligence_with_jason&quot;&gt;Comprehensive Project Intelligence with Jason van Zyl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/what_s_coming_in_spring&quot;&gt;What&apos;s Coming in Spring 3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/applying_flash_to_java_flex&quot;&gt;Applying Flash to Java: Flex and OpenLaszlo with Dustin Marx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/building_rich_applications_with_appcelerator&quot;&gt;Building Rich Applications with Appcelerator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/taking_apache_camel_for_a&quot;&gt;Taking Apache Camel for a Ride with Bruce Snyder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/core_animation_with_bill_dudney&quot;&gt;Core Animation with Bill Dudney&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://raibledesigns.com/rd/entry/restful_web_applications_with_subbu&quot;&gt;RESTful Web Applications with Subbu Allamaraju&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;p&gt;For next year, I think the conference should shorten its sessions (from 90 to 60 minutes), invite more speakers and cut the price in half (to $999 per person). How do you think the Software Summit could be improved?</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/comprehensive_project_intelligence_with_jason</guid>
    <title>Comprehensive Project Intelligence with Jason van Zyl</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/comprehensive_project_intelligence_with_jason</link>
        <pubDate>Tue, 21 Oct 2008 14:35:13 -0600</pubDate>
    <category>Java</category>
    <category>m2eclipse</category>
    <category>softwaresummit</category>
    <category>hudson</category>
    <category>maven</category>
    <category>nexus</category>
            <description>In this talk, &lt;a href=&quot;http://blogs.sonatype.com/people/jvanzyl/&quot;&gt;Jason&lt;/a&gt; is going to talk about &lt;a href=&quot;http://m2eclipse.codehaus.org/&quot;&gt;m2eclipse&lt;/a&gt;, &lt;a href=&quot;http://nexus.sonatype.org/&quot;&gt;Nexus&lt;/a&gt;, &lt;a href=&quot;https://hudson.dev.java.net/&quot;&gt;Hudson&lt;/a&gt; and &lt;a href=&quot;http://maven.apache.org/&quot;&gt;Maven&lt;/a&gt;. On his Maven bullet-point, it says &quot;The best is yet to come (and we&apos;ll fix a bunch of stuff)!&quot; 
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;m2eclipse&lt;/strong&gt;&lt;br/&gt;The m2eclipse plugin has improved greatly in the last 4 months - there&apos;s now 5 full-time developers working on it. If you use the m2eclipse plugin, you never have to leave the IDE for your Maven-related work. m2eclipse has a Configuration Framework that turns Maven&apos;s mumbo-jumbo (Jason&apos;s words, not mine) into Eclipse talk. The m2eclipse+configuration framework has integration for WTP, JDT, AJDT and they&apos;re working on one for Flex. Below is a screenshot of how m2eclipse helps developers stay away from using command-line Maven.&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;
&lt;a href=&quot;http://farm4.static.flickr.com/3042/2962624266_05dc42835c_o.png&quot; title=&quot;m2eclipse Configuration Framework&quot; rel=&quot;lightbox[m2eclipse]&quot;&gt;&lt;img src=&quot;//farm4.static.flickr.com/3042/2962624266_cbf14978ff_m.jpg&quot; width=&quot;240&quot; height=&quot;188&quot; alt=&quot;m2eclipse Configuration Framework&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Now Jason is showing a demo of m2eclipse and creating a new Maven project from existing archetypes. It looks like m2eclipse uses &quot;Nexus Indexer&quot; as its Catalog. Presumably this is a Sonatype-hosted service. The Nexus Indexer contains an of Maven Central and is very fast. It&apos;s dynamically updated as new things are deployed to Maven Central.&lt;/p&gt;

&lt;p&gt;If you use m2eclipse and open a pom.xml, you&apos;ll get a visual view rather than an XML view. This UI has tabs for Overview, Dependencies, Repositories, Build, Plugins, Reporting, Profiles, Team, a Dependency Hierarchy and Dependency Graph. You can easily add new dependencies and it finds things quickly because it&apos;s using the Nexus index. In addition to visually adding dependencies, you can modify the raw XML and get things like groupId and version code-completion. 
&lt;/p&gt;
&lt;p&gt;
Once you have your dependencies listed in a &quot;Maven Dependencies&quot; container to you can &quot;Materialize Project&quot; to create a project from the binary dependency. You&apos;ll get the source as a new project in your workspace as well as having your binary dependency turned into a source dependency.&lt;/p&gt;

&lt;p&gt;You can easily create a run configuration that runs certain goals, allows you to activate profiles and uses an embedded version of Maven or an external installation. I asked Jason if the Dependency Hierarchy had a right-click -&gt; exclude feature and he said it doesn&apos;t exist yet, but it will in the release after next. For now, the &lt;em&gt;pom editor&lt;/em&gt; is just eye candy and doesn&apos;t have actions.
&lt;/p&gt;
&lt;p&gt;For Maven Plugins, m2eclipse has workspace resolution so you can develop a plugin and use it in a project at the same time w/o having to install the plugin over and over.&lt;/p&gt;
&lt;p&gt;Sonatype has created a Project Materializer Plugin that allows a team lead to create a project for developers. It allows you to create a welcome page that has links, cheat sheets, News and Updates and Tasks for the developer. It also materializes Eclipse projects in the background. Cheat Sheets are a series of tasks that can be run to show developers how to do things.&lt;/p&gt;
&lt;p&gt;Another big feature in m2eclipse is nested project support. It only works in Eclipse 3.4 though.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nexus&lt;/strong&gt;&lt;br/&gt;Nexus is a repository manager that allows you to keep the cruft from the outside world out of your system. It&apos;s primarily for Repository and Configuration Management. It has fine-grained security for authentication and authorization.  One nice feature of its security system is you can prevent certain users from seeing source JARs. It also has &lt;em&gt;virtual&lt;/em&gt; repositories (a savior for OSGi lovers). UI is written in Ext JS and acts as a simple REST client for Nexus. It has a full REST API using RESTlet.
&lt;/p&gt;&lt;p&gt;A repository manager allows you to protect yourself from the &lt;strong&gt;Open Source Ghetto&lt;/strong&gt;. The OS Maven Ghetto has bad POMs, repositories in POMs, mixed snapshot and release dependencies and screwed up metadata. Not only does it offer protection, but it allows you to aggregate repositories and publish your internal artifacts to it. It also allows you to schedule tasks that clean out snapshots so your repositories don&apos;t grow out of control.
&lt;/p&gt;
&lt;p&gt;Typically people deal with OSGi runtimes manually. OSGi can dynamically update dependencies that you drop into your bundle repository. However, many folks maintain their OSGi runtime and bundle repository locally. Some people are trying to get an OSGi runtime to resolve against a P2 repository. P2 is what Eclipse uses for their repository management. Nexus has the ability to lock down the versions that are available to an OSGi runtime. Furthermore, you can use Nexus to manage the versions that get deployed to all your servers. This makes it a lot easier for QA and Production to manage versions of your artifacts. OSGi is great for modularity and solving classpath issues, but it does have issues with versions and how its ranges work.&lt;/p&gt;
&lt;p&gt;You can see Nexus in action at &lt;a href=&quot;http://repository.sonatype.org/&quot;&gt;http://repository.sonatype.org&lt;/a&gt;. It can be configured entirely through the UI, an XML file or through the REST API. RSS feeds exist for configuration and repository updates.
&lt;/p&gt;
&lt;p&gt;Nexus is free and open source with a GPL license. The next version (1.2) will contain a Plugin API to allow extensions. All of Sonatype&apos;s enhancements for its commercial version will be written as plugins. A matrix of what&apos;s available in the open source version vs. commercial version should be published sometime next week.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hudson&lt;/strong&gt;&lt;br/&gt;
Jason believes that Hudson is the future of continuous integration, on-demand results and release management. They&apos;re writing all their extension points in Hudson as Maven plugins and Plexus components (with the work they&apos;ve done, using Spring components should also be possible). Other enhancements they&apos;ve made to Hudson:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integration of JSecurity&lt;/li&gt;
&lt;li&gt;Implementing a similar REST layer as Nexus and creating a UI using Ext JS&lt;/li&gt;
&lt;li&gt;Automatic installation of external Maven installations&lt;/li&gt;
&lt;li&gt;Drools Workflow Integration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They&apos;ve also enhanced Hudson so it can easily test/publish Maven projects without using the free-form project template. Hudson works well for doing Eclipse headless builds for Eclipse plugins. If you need to test against multiple databases, multiple OS&apos;s, it does support a grid-based system that&apos;s easy to setup. Hudson does have web services integration that allows you to kick off builds from within Eclipse. Sonatype uses Hudson to run all their nightly builds of Maven.
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Maven - the best is yet to come&lt;/strong&gt;&lt;br/&gt;
The three big things coming in the next version of Maven are:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Refactored Project Builder: includes a spec for building a pom, domain-specific parsers (attribute-based XML, Groovy and Ruby) and mixins.&lt;/li&gt;
&lt;li&gt;Mercury: a new repository and transport layer. Developed by the Jetty people and is super fast (async client with connection pooling and parallelization). Has atomic downloads and deployments (with Nexus), full PGP support and a WebDAV client built-in.&lt;/li&gt;
&lt;li&gt;Maven Embedder: re-written to actually work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Overall, a good talk with lots of demos. I&apos;m definitely looking forward to Maven improvements in the future.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/maven_plugin_for_running_integration</guid>
    <title>Maven Plugin for Running Integration Tests against Multiple Containers</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/maven_plugin_for_running_integration</link>
        <pubDate>Thu, 31 Jul 2008 17:39:23 -0600</pubDate>
    <category>Java</category>
    <category>testing</category>
    <category>maven</category>
    <category>java</category>
    <category>cargo</category>
            <description>Don Brown has created a pretty cool Maven plugin that allows you to run integration tests on multiple containers in one go. I learned about it on the &lt;a href=&quot;http://markmail.org/message/ra6c5quscjgrdkqt&quot;&gt;Struts 2 Dev List&lt;/a&gt;:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
I&apos;ve started adding functional tests to Struts 2 by adding a few to the REST showcase application, running against Tomcat 5.x, Jetty 6.x, JBoss 4.2.x, and Resin 3.x. The magic happens through a new Maven 2 plugin I developed called maven-itblast-plugin, which enables multiple integration test runs against multiple containers in one go. For more info, see &lt;a href=&quot;http://github.com/mrdon/maven-itblast-plugin/wikis/home&quot;&gt;http://github.com/mrdon/maven-itblast-plugin/wikis/home&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You might notice that this plugin is hosted on &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;. If you want to learn how to use GitHub with Maven, you might want to see Don&apos;s entry on &lt;a href=&quot;http://www.jroller.com/mrdon/entry/maven_enabled_project_hosting_with&quot;&gt;Maven-enabled project hosting with GitHub&lt;/a&gt;. Thanks Don - good stuff.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Don has posted &lt;a href=&quot;http://www.jroller.com/mrdon/entry/run_integration_tests_on_multiple&quot;&gt;more information about this plugin&lt;/a&gt; on his blog.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/issues_with_antrun_plugin_and</guid>
    <title>Issues with AntRun Plugin and Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/issues_with_antrun_plugin_and</link>
        <pubDate>Sat, 10 May 2008 18:23:26 -0600</pubDate>
    <category>Java</category>
    <category>ant</category>
    <category>maven</category>
            <description>I started seeing the following error today when using Maven and the AntRun Plugin.&lt;/p&gt;
&lt;pre&gt;
[INFO] [antrun:run {execution: default}]
[INFO] Executing tasks
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Error executing ant tasks
	
Embedded error: java.lang.IllegalAccessError: tried to access method 
org.apache.tools.ant.launch.Locator.decodeUri(Ljava/lang/String;)Ljava/lang/String; 
from class org.apache.tools.ant.AntClassLoader
&lt;/pre&gt;
&lt;p&gt;Searching the internet provided no results, so I was pretty stumped - especially since this error didn&apos;t happen on my MacBook Pro. It happened on &lt;a href=&quot;http://builds.appfuse.org&quot;&gt;AppFuse&apos;s Bamboo&lt;/a&gt; server (Linux), but not locally. Luckily, I was able to reproduce it on my Windows box and discovered the solution: &lt;strong&gt;upgrade to a newer version of Maven&lt;/strong&gt;. I was using 2.0.6/2.0.7 and upgrading to 2.0.9 fixed the problem.&lt;/p&gt;
&lt;p&gt;BTW, when is the Ant project going to release a new version of Ant? The current 1.7.0 version &lt;a href=&quot;http://issues.appfuse.org/browse/APF-970&quot;&gt;doesn&apos;t support spaces in path names&lt;/a&gt;, which seems like a pretty big issue to me (especially for Windows users).</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/running_spring_mvc_web_applications</guid>
    <title>Running Spring MVC Web Applications in OSGi</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/running_spring_mvc_web_applications</link>
        <pubDate>Wed, 30 Apr 2008 00:42:34 -0600</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>springmvc</category>
    <category>osgi</category>
    <category>equinox</category>
    <category>spring</category>
            <description>For the past couple of weeks, I&apos;ve been developing a web application that deploys into an OSGi container (Equinox) and uses Spring DM&apos;s &lt;a href=&quot;http://static.springframework.org/osgi/docs/1.1.0-m2/reference/html/web.html#web:spring-mvc&quot;&gt;Spring MVC support&lt;/a&gt;. The first thing I discovered was that Spring MVC&apos;s annotations weren&apos;t supported in the M1 release. This was apparently caused by a &lt;a href=&quot;http://groups.google.com/group/spring-osgi/browse_thread/thread/cf1fa802f846feac/b0f7483ea63b8f8e?lnk=gst#b0f7483ea63b8f8e&quot;&gt;bug &lt;/a&gt; in Spring 2.5.3 and not Spring DM. Since Spring DM 1.1.0 M2 was released with Spring 2.5.4 &lt;a href=&quot;http://www.springframework.org/node/646&quot;&gt;today&lt;/a&gt;, I believe this is fixed now.
&lt;/p&gt;
&lt;p&gt;The story below is about my experience getting a Spring MVC application up and running in Equinox 3.2.2, Jetty 6.1.9 and Spring DM 1.1.0 M2 SNAPSHOT (from last week). If you want to read more about why Spring MVC + OSGi is cool, see Costin Leau&apos;s &lt;a href=&quot;http://blog.springsource.com/main/2008/04/29/web-applications-and-osgi/&quot;&gt;Web Applications and OSGi&lt;/a&gt; article.&lt;/p&gt;
&lt;p&gt;To get a simple &quot;Hello World&quot; Spring MVC application working in OSGi is pretty easy. The hard part is setting up a container with all the Spring and Jetty bundles installed and started. I imagine &lt;a href=&quot;http://www.infoq.com/news/2008/04/springsource-app-platform&quot;&gt;SSAP&lt;/a&gt; might solve this. Luckily for me, this was done by another member of my team.&lt;/p&gt;
&lt;p&gt;After you&apos;ve done this, it&apos;s simply a matter of creating a MANIFEST.MF for your WAR that contains the proper information for OSGi to recognize. Below is the one that I used when I first tried to get my application working. 
&lt;/p&gt;
&lt;pre&gt;
Manifest-Version: 1
Bundle-ManifestVersion: 2
Spring-DM-Version: 1.1.0-m2-SNAPSHOT
Spring-Version: 2.5.2
Bundle-Name: Simple OSGi War
Bundle-SymbolicName: myapp
Bundle-Classpath: .,WEB-INF/classes,WEB-INF/lib/freemarker-2.3.12.jar,
 WEB-INF/lib/sitemesh-2.3.jar,WEB-INF/lib/urlrewritefilter-3.0.4.jar,
 WEB-INF/lib/spring-beans-2.5.2.jar,WEB-INF/lib/spring-context-2.5.2.jar,
 WEB-INF/lib/spring-context-support-2.5.2.jar,WEB-INF/lib/spring-core-2.5.2.jar,
 WEB-INF/lib/spring-web-2.5.2.jar,WEB-INF/lib/spring-webmvc-2.5.2.jar 
Import-Package: javax.servlet,javax.servlet.http,javax.servlet.resources,javax.swing.tree,
 javax.naming,org.w3c.dom,org.apache.commons.logging,javax.xml.parsers;resolution:=optional,
 org.xml.sax;resolution:=optional,org.xml.sax.helpers;resolution:=optional
&lt;/pre&gt;
&lt;p class=&quot;smokey&quot;&gt;Ideally, you could generate this MANIFEST.MF using the &lt;a href=&quot;http://felix.apache.org/site/maven-bundle-plugin-bnd.html&quot;&gt;maven-bundle-plugin&lt;/a&gt;. However, it &lt;a href=&quot;http://www.nabble.com/Is-it-possible-to-use-the-maven-bundle-plugin-on-a-WAR-project--ts16763483.html&quot;&gt;doesn&apos;t support WARs&lt;/a&gt; in its 1.4.0 release.&lt;/p&gt;

&lt;p&gt;You can see this is an application that uses Spring MVC, FreeMarker, SiteMesh and the URLRewriteFilter. You should be able to &lt;a href=&quot;http://static.raibledesigns.com/downloads/myapp-noosgi.zip&quot;&gt;download it&lt;/a&gt;, unzip it, run &quot;mvn package&quot; and install it into Equinox using &quot;install file://&amp;lt;path to war&gt;&quot;.&lt;/p&gt;
&lt;p&gt;That&apos;s all fine and dandy, but doesn&apos;t give you any benefits of OSGi. This setup works great until you try to import OSGi services using a context file with an &lt;strong&gt;&amp;lt;osgi:reference&gt;&lt;/strong&gt; element. After adding such a reference, it&apos;s likely you&apos;ll get the following error:
&lt;/p&gt;
&lt;pre&gt;
SEVERE: Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException:
Configuration problem: Unable to locate Spring NamespaceHandler for
XML schema namespace [http://www.springframework.org/schema/osgi]
&lt;/pre&gt;
&lt;p&gt;To fix this, add the following to your web.xml (if you&apos;re using ContextLoaderListener, as an &amp;lt;init-parameter&amp;gt; on DispatcherServlet if you&apos;re not):&lt;/p&gt;
&lt;pre&gt;
  &amp;lt;context-param&amp;gt;
    &amp;lt;param-name&amp;gt;contextClass&amp;lt;/param-name&amp;gt;
    &amp;lt;param-value&amp;gt;org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext&amp;lt;/param-value&amp;gt;
  &amp;lt;/context-param&amp;gt;
&lt;/pre&gt;
&lt;p&gt;After doing this, you might get the following error on startup:&lt;/p&gt;
&lt;pre&gt;
SEVERE: Context initialization failed
org.springframework.context.ApplicationContextException: Custom
context class [org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext]
is not of type [org.springframework.web.context.ConfigurableWebApplicationContext] 
&lt;/pre&gt;
&lt;p&gt;To fix this, I change from referencing the Spring JARs in WEB-INF/lib
to importing the packages for Spring (which were already installed in my
Equinox container).
&lt;/p&gt;
&lt;pre&gt;
Bundle-Classpath: .,WEB-INF/classes,WEB-INF/lib/freemarker-2.3.12.jar,
 WEB-INF/lib/sitemesh-2.3.jar,WEB-INF/lib/urlrewritefilter-3.0.4.jar
Import-Package:
javax.servlet,javax.servlet.http,javax.servlet.resources,javax.swing.tree,
 javax.naming,org.w3c.dom,org.apache.commons.logging,javax.xml.parsers;resolution:=optional,
 org.xml.sax;resolution:=optional,org.xml.sax.helpers;resolution:=optional,
 org.springframework.osgi.web.context.support,
 org.springframework.context.support,
 org.springframework.web.context,
 org.springframework.web.context.support,
 org.springframework.web.servlet,
 org.springframework.web.servlet.mvc,
 org.springframework.web.servlet.mvc.support,
 org.springframework.web.servlet.view,
 org.springframework.ui,
 org.springframework.web.servlet.view.freemarker 
&lt;/pre&gt;
&lt;p&gt;After rebuilding my WAR and reloading the bundle in Equinox, I was confronted with the following error message:&lt;/p&gt;
&lt;pre&gt;
SEVERE: Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name &apos;freemarkerConfig&apos; defined in ServletContext
resource [/WEB-INF/myapp-servlet.xml]: Instantiation of bean failed;
nested exception is java.lang.NoClassDefFoundError:
freemarker/cache/TemplateLoader
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:851) 
&lt;/pre&gt;
&lt;p&gt;As far as I can tell, this is because the version of Spring MVC installed in Equinox
cannot resolve the FreeMarker JAR in my WEB-INF/lib directory.
&lt;/p&gt;
&lt;p&gt;To prove I wasn&apos;t going insane, I commented out my &quot;freemarkerConfig&quot; and &quot;viewResolver&quot; beans in myapp-servlet.xml and changed to a regular ol&apos; InternalResourceViewResolver:&lt;/p&gt;
&lt;pre&gt;
&amp;lt;bean id=&quot;viewResolver&quot; class=&quot;org.springframework.web.servlet.view.InternalResourceViewResolver&quot;&amp;gt;
    &amp;lt;property name=&quot;prefix&quot; value=&quot;/&quot;/&amp;gt;
    &amp;lt;property name=&quot;suffix&quot; value=&quot;.jsp&quot;/&amp;gt;
&amp;lt;/bean&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This worked and I was able to successfully see &quot;Hello World&quot; from a JSP in my browser. FreeMarker/SiteMesh worked too, but FreeMarker didn&apos;t work as a View for Spring MVC.
&lt;/p&gt;
&lt;p&gt;
To attempt to solve this, I create a &lt;a href=&quot;http://static.raibledesigns.com/downloads/freemarker-2.3.12-bundle.jar&quot;&gt;bundle for FreeMarker&lt;/a&gt; using &quot;java -jar
bnd-0.0.249.jar wrap freemarker-2.3.12.jar&quot; and installed it in Equinox.
I then change my MANIFEST.MF to use FreeMarker imports instead of
referencing the JAR in WEB-INF/lib.
&lt;/p&gt;
&lt;pre&gt;
Bundle-Classpath:
.,WEB-INF/classes,WEB-INF/lib/sitemesh-2.3.jar,WEB-INF/lib/urlrewritefilter-3.0.4.jar
Import-Package:
javax.servlet,javax.servlet.http,javax.servlet.resources,javax.swing.tree,
 javax.naming,org.w3c.dom,org.apache.commons.logging,javax.xml.parsers;resolution:=optional,
 org.xml.sax;resolution:=optional,org.xml.sax.helpers;resolution:=optional,
 org.springframework.osgi.web.context.support,
 org.springframework.context.support,
 org.springframework.web.context,
 org.springframework.web.context.support,
 org.springframework.web.servlet,
 org.springframework.web.servlet.mvc,
 org.springframework.web.servlet.mvc.support,
 org.springframework.web.servlet.view,
 org.springframework.ui,
 org.springframework.web.servlet.view.freemarker,
 freemarker.cache,freemarker.core,freemarker.template,freemarker.ext.servlet 
&lt;/pre&gt;
&lt;p&gt;Unfortunately, this still doesn&apos;t work and I still haven&apos;t been able to get FreeMarker to work with Spring MVC in OSGi. The crazy thing is I actually solved this at one point a week ago. Shortly after, I rebuilt Equinox from scratch and I&apos;m been banging my head against the wall over this issue ever since. Last week, I entered an &lt;a href=&quot;http://jira.springframework.org/browse/OSGI-461&quot;&gt;issue in Spring&apos;s JIRA&lt;/a&gt;, but thought I&apos;d fixed it a few hours later.
&lt;/p&gt;
&lt;p&gt;
I&apos;ve uploaded the final project that&apos;s not working to the following URL:&lt;/p&gt;
&lt;p style=&quot;padding-left: 15px&quot;&gt;&lt;a href=&quot;http://static.raibledesigns.com/downloads/myapp-osgi.zip&quot;&gt;http://static.raibledesigns.com/downloads/myapp-osgi.zip&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;If you&apos;d like to see this project work with Spring MVC + JSP, simply modify myapp-servlet.xml to remove the FreeMarker references and use the InternalResourceViewResolver instead.&lt;/p&gt;
&lt;p&gt;I hope Spring DM + Spring MVC supports more than just JSP as a view technology. I hope I can&apos;t get FreeMarker working because of some oversight on my part. 
If you have a Spring DM + Spring MVC application working with Velocity or FreeMarker, I&apos;d love to hear about it.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/maven_integration_for_eclipse</guid>
    <title>Maven Integration for Eclipse</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/maven_integration_for_eclipse</link>
        <pubDate>Wed, 12 Mar 2008 16:22:43 -0600</pubDate>
    <category>Java</category>
    <category>java</category>
    <category>maven</category>
    <category>eclipse</category>
            <description>If you&apos;re a &lt;a href=&quot;http://maven.apache.org&quot;&gt;Maven&lt;/a&gt; user and like Eclipse, you might want to checkout the &lt;a href=&quot;http://www.jroller.com/eu/entry/m2eclipse_0_9_0&quot;&gt;new
Maven Integration Plugin for Eclipse 0.9.0&lt;/a&gt;. Euxx has a couple blog posts talking about the new features - looks like pretty cool stuff to me.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.jroller.com/eu/entry/maven_indexes&quot;&gt;Indexing Maven repositories&lt;/a&gt; - for offline browsing of repositories.
&lt;img src=&quot;//www.jroller.com/eu/resource/mavenindexesviewtc.png&quot; width=&quot;371&quot; height=&quot;283&quot; alt=&quot;Offline Browsing&quot; style=&quot;margin: 10px; border: 1px solid silver&quot; /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;&quot;&gt;Making a good use of Maven metadata&lt;/a&gt; - materializing projects from dependencies.
&lt;br/&gt;
&lt;img src=&quot;//www.jroller.com/eu/resource/mavenmaterialize1.png&quot; width=&quot;369&quot; height=&quot;398&quot; alt=&quot;Materialize Project&quot; style=&quot;margin: 10px; border: 1px solid silver&quot; /&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The second feature is especially cool. If your dependencies supply SCM information - you can import the project from its source control system. Maven may have warts, but it also has incredible potential.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/maven_now_supports_attributes_in</guid>
    <title>Maven now supports attributes in pom.xml?!</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/maven_now_supports_attributes_in</link>
        <pubDate>Mon, 11 Feb 2008 15:45:57 -0700</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>xml</category>
            <description>In December 2005, I asked &lt;a href=&quot;http://www.nabble.com/Is-it-possible-to-make-pom.xml-simpler--to1950833s177.html#a1974889&quot;&gt;Is it possible to make pom.xml simpler?&lt;/a&gt;. &lt;/p&gt;
&lt;div class=&quot;quote&quot; style=&quot;color: #666; margin: 10px; margin-left: 0px&quot;&gt;
&lt;p&gt;After seeing what the Spring Developers have done to simplify Spring 
context files, I can&apos;t help but think the same thing is possible for 
Maven 2&apos;s pom.xml.  Is it possible to add namespaces and make 
something like the following possible? 
&lt;/p&gt;
&lt;p&gt;
Before:&lt;/p&gt;
&lt;pre&gt;
    &amp;lt;dependency&amp;gt; 
      &amp;lt;groupId&amp;gt;springframework&amp;lt;/groupId&amp;gt; 
      &amp;lt;artifactId&amp;gt;spring&amp;lt;/artifactId&amp;gt; 
      &amp;lt;version&amp;gt;1.2.6&amp;lt;/version&amp;gt; 
    &amp;lt;/dependency&amp;gt; 
&lt;/pre&gt;
&lt;p&gt;
After: &lt;/p&gt;

&lt;pre&gt;&amp;lt;dep:artifact name=&quot;org/springframework/spring&quot; version=&quot;1.2.6&quot;/&amp;gt;&lt;/pre&gt;
&lt;p&gt;
Or just allow attributes to make things a bit cleaner? &lt;/p&gt;

&lt;pre&gt;&amp;lt;dependency groupId=&quot;org.springframework&quot; artifactId=&quot;spring&quot; version=&quot;1.2.6&quot;/&amp;gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;At that time, the general response was &quot;That&apos;s how Maven works. It&apos;s a matter of taste. You&apos;ll get used to it.&quot; It&apos;s been two years and sure, I&apos;m used to it, but I&apos;d still rather write less XML. That&apos;s why I was particularly pleased to see Brett Porter&apos;s write &lt;a href=&quot;http://blogs.exist.com/bporter/2008/02/11/maven-now-supports-condensed-poms-using-attributes/&quot;&gt;Maven now supports condensed POMs using attributes&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;quote&quot; style=&quot;color: #666; margin: 10px; margin-left: 0px&quot;&gt;
&lt;p&gt;The issue is being tracked under &lt;a href=&quot;http://jira.codehaus.org/browse/MNG-3397&quot;&gt;MNG-3397&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The result is that something &lt;a href=&quot;http://svn.apache.org/viewvc/maven/archiva/trunk/pom.xml?content-type=text%2Fplain&amp;amp;view=co&quot;&gt;like this&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;junit&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;junit&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;3.8.1&amp;lt;/version&amp;gt;
  &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;easymock&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;easymock&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;1.2_Java1.3&amp;lt;/version&amp;gt;
  &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
...
&lt;/pre&gt;

&lt;p&gt;Halves in length to something &lt;a href=&quot;http://svn.apache.org/viewvc/maven/archiva/trunk/pom-4.1.0.xml?content-type=text%2Fplain&amp;amp;view=co&quot;&gt;like this&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;dependency groupId=&quot;junit&quot; artifactId=&quot;junit&quot; version=&quot;3.8.1&quot; scope=&quot;test&quot;/&amp;gt;
&amp;lt;dependency groupId=&quot;easymock&quot; artifactId=&quot;easymock&quot; version=&quot;1.2_Java1.3&quot; scope=&quot;test&quot;/&amp;gt;
...
&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Now that wasn&apos;t so hard was it? &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;
</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/building_a_better_maven_with</guid>
    <title>Building a Better Maven with Ant</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/building_a_better_maven_with</link>
        <pubDate>Mon, 11 Feb 2008 14:07:12 -0700</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>ant</category>
            <description>It looks like the &lt;a href=&quot;http://www.nabble.com/-DISCUSS--EasyAnt%3A-Ant-based-pre-packaged-build-system-for-java-projects-td14735371.html&quot;&gt;Ant folks are thinking of building a better Maven&lt;/a&gt;.&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
I see many developers adopt Maven because they want a build system able to
provide common features with no effort. Most of them don&apos;t want to spend
much time writing an Ant script, or have seen or heard that maintaining Ant
build scripts is troublesome. So they choose to use Maven only because it&apos;s
easy to use for common use cases: install, write a simple pom of a few lines
or generate it using an archetype, and you&apos;re ready to compile, test and
package your new project following the Maven standard structure. They also
get dependency management for free, and with only a few more effort they
have multi module builds, and some nice features like code analysis,
coverage, and a set of report gathered in a web site. That&apos;s really nice and
that&apos;s what I like about Maven.
&lt;br/&gt;&lt;br/&gt;
But Maven suffers from a lack of flexibility and robustness IMHO. And later
the same people who first adopted Maven because of its perceived ease of use
become frustrated when they need to tweek the system to their own needs or
don&apos;t understand how the release plugin work. Then some of them go back to
Ant, first having to go through a sometimes painful road to describe their
whole build system in xml, especially if they aren&apos;t Ant experts. Others try
to use new build tools like raven, buildr or others.
&lt;br/&gt;&lt;br/&gt;
I really like Ant, and think it is a very good basis for robust and flexible
build systems. People with enough knowledge of Ant can write very good build
systems, testable, maintainable and adaptable. But you need to get your
hands dirty, and you need to get a good knowledge of some of the mechanisms
which can make an Ant based build system manageable: import, scripts and
scriptdef, macrodef, presetdef, and so on. [&lt;a href=&quot;http://www.nabble.com/-DISCUSS--EasyAnt%3A-Ant-based-pre-packaged-build-system-for-java-projects-td14735371.html&quot;&gt;Read More&lt;/a&gt;]
&lt;/p&gt;
&lt;p&gt;
What do you think - is this a good idea? 
&lt;/p&gt;
&lt;p&gt;
I agree that Maven has its warts, but I don&apos;t think it&apos;s &lt;em&gt;that&lt;/em&gt; bad. I&apos;ve also heard that Maven has been successfully implemented at large companyies like eBay, Intuit and E*Trade[1]. Is the &quot;Maven sucks&quot; meme largely something that exists in the blogosphere, but not in the real world?
&lt;/p&gt;
&lt;p&gt;I think the biggest benefit of Maven is dependency management. I think it makes your code more modular and easier to build. Rather than having a monolithic source-code tree that depends on itself being built in a certain order, you can have individual modules that pull dependencies from a central location. This can be done with Maven&apos;s Ant Tasks as well. I don&apos;t see a problem with building a better Maven with Ant, but to try and build a better Central Repository sounds like a nightmare to me. The current repository has been improved for years and is much better than it was a couple years ago. That being said, I would &lt;em&gt;love&lt;/em&gt; to see somebody build a more accurate Central Repository. Ideally, it&apos;d be done sometime next week. &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;&lt;/p&gt;
&lt;p&gt;[1] I could be wrong about these companies. If you&apos;re a developer at one of these companies, please confirm or deny. Any comments on Maven&apos;s success at these companies would be great as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Speaking of Maven, there&apos;s &lt;a href=&quot;http://java.dzone.com/news/don-brown-makes-maven-2-not-su#comment-775&quot;&gt;an interesting comment on a Javalobby post I wrote&lt;/a&gt;:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
With all the critical remarks the Maven project is receiving, wouldn&apos;t it be time for some Maven project lead to step up and explain the team&apos;s position? Or is it completely deaf to the sentiments? How many builds have to fail, how much more headaches are needed before others start their own version of Maven and do it the right way (like Don [Brown])?
&lt;/p&gt;
&lt;p&gt;Seems like an excellent question to me. Guys?</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/maven_2_archetypes_get_a</guid>
    <title>Maven 2 Archetypes get a much needed improvement</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/maven_2_archetypes_get_a</link>
        <pubDate>Sat, 9 Feb 2008 15:20:00 -0700</pubDate>
    <category>Java</category>
    <category>maven</category>
    <atom:summary type="html">Yesterday, a &lt;a href=&quot;http://markmail.org/message/ivskpgvts6kvhjh3&quot;&gt;new version of the Maven Archetype Plugin was released&lt;/a&gt;. This release incorporates many of the improvements that were developed in a different project - code named &quot;Archetype NG&quot;. The two major improvements are 1) you only have to use &quot;mvn archetype:create&quot; now and 2) you can create archetypes from existing projects.&lt;/p&gt;
&lt;p&gt;I haven&apos;t tried #2, but #1 seems to work pretty well (especially since AppFuse archetypes are the first 9 &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;).&lt;br/&gt;&lt;br/&gt;</atom:summary>        <description>Yesterday, a &lt;a href=&quot;http://markmail.org/message/ivskpgvts6kvhjh3&quot;&gt;new version of the Maven Archetype Plugin was released&lt;/a&gt;. This release incorporates many of the improvements that were developed in a different project - code named &quot;Archetype NG&quot;. The two major improvements are 1) you only have to use &quot;mvn archetype:create&quot; now and 2) you can create archetypes from existing projects.&lt;/p&gt;
&lt;p&gt;I haven&apos;t tried #2, but #1 seems to work pretty well (especially since AppFuse archetypes are the first 9 &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;).&lt;/p&gt;
&lt;pre&gt;
powers:~ mraible$ mvn archetype:create
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: &apos;archetype&apos;.
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Default Project
[INFO]    task-segment: [archetype:create] (aggregator-style)
[INFO] ------------------------------------------------------------------------
[INFO] Preparing archetype:create
[INFO] No goals needed for project - skipping
[INFO] Setting property: classpath.resource.loader.class =&gt; &apos;org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader&apos;.
[INFO] Setting property: velocimacro.messages.on =&gt; &apos;false&apos;.
[INFO] Setting property: resource.loader =&gt; &apos;classpath&apos;.
[INFO] Setting property: resource.manager.logwhenfound =&gt; &apos;false&apos;.
[INFO] [archetype:create]
Choose archetype:
1: internal -&gt; appfuse-basic-jsf (AppFuse archetype for creating a web application with Hibernate, Spring and JSF)
2: internal -&gt; appfuse-basic-spring (AppFuse archetype for creating a web application with Hibernate, Spring and Spring MVC)
3: internal -&gt; appfuse-basic-struts (AppFuse archetype for creating a web application with Hibernate, Spring and Struts 2)
4: internal -&gt; appfuse-basic-tapestry (AppFuse archetype for creating a web application with Hibernate, Spring and Tapestry 4)
5: internal -&gt; appfuse-core (AppFuse archetype for creating a jar application with Hibernate and Spring and XFire)
6: internal -&gt; appfuse-modular-jsf (AppFuse archetype for creating a modular application with Hibernate, Spring and JSF)
7: internal -&gt; appfuse-modular-spring (AppFuse archetype for creating a modular application with Hibernate, Spring and Spring MVC)
8: internal -&gt; appfuse-modular-struts (AppFuse archetype for creating a modular application with Hibernate, Spring and Struts 2)
9: internal -&gt; appfuse-modular-tapestry (AppFuse archetype for creating a modular application with Hibernate, Spring and Tapestry 4)
10: internal -&gt; maven-archetype-j2ee-simple (A simple J2EE Java application)
11: internal -&gt; maven-archetype-marmalade-mojo (A Maven plugin development project using marmalade)
12: internal -&gt; maven-archetype-mojo (A Maven Java plugin development project)
13: internal -&gt; maven-archetype-portlet (A simple portlet application)
14: internal -&gt; maven-archetype-profiles ()
15: internal -&gt; maven-archetype-quickstart ()
16: internal -&gt; maven-archetype-site-simple (A simple site generation project)
17: internal -&gt; maven-archetype-site (A more complex site project)
18: internal -&gt; maven-archetype-webapp (A simple Java web application)
19: internal -&gt; struts2-archetype-starter (A starter Struts 2 application with Sitemesh, DWR, and Spring)
20: internal -&gt; struts2-archetype-blank (A minimal Struts 2 application)
21: internal -&gt; struts2-archetype-portlet (A minimal Struts 2 application that can be deployed as a portlet)
22: internal -&gt; struts2-archetype-dbportlet (A starter Struts 2 portlet that demonstrates a simple CRUD interface with db backing)
23: internal -&gt; struts2-archetype-plugin (A Struts 2 plugin)
24: internal -&gt; shale-archetype-blank (A blank Shale web application with JSF)
25: internal -&gt; maven-adf-archetype (Archetype to ease the burden of creating a new application based with ADF)
26: internal -&gt; data-app (A new Databinder application with sources and resources.)
27: internal -&gt; jini-service-archetype (Archetype for Jini service project creation)
28: internal -&gt; softeu-archetype-seam (JSF+Facelets+Seam Archetype)
29: internal -&gt; softeu-archetype-seam-simple (JSF+Facelets+Seam (no persistence) Archetype)
30: internal -&gt; softeu-archetype-jsf (JSF+Facelets Archetype)
31: internal -&gt; jpa-maven-archetype (JPA application)
32: internal -&gt; spring-osgi-bundle-archetype (Spring-OSGi archetype)
33: internal -&gt; confluence-plugin-archetype (Atlassian Confluence plugin archetype)
34: internal -&gt; maven-archetype-har (Hibernate Archive)
35: internal -&gt; maven-archetype-sar (JBoss Service Archive)
36: internal -&gt; wicket-archetype-quickstart (A simple Apache Wicket project)
Choose a number:  (1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30/31/32/33/34/35/36): 3
Downloading: http://static.appfuse.org/releases/org/appfuse/archetypes/appfuse-basic-struts/2.0/appfuse-basic-struts-2.0.jar
71K downloaded
Define value for groupId: : com.company
Define value for artifactId: : myapp
Define value for version: : 1.0-SNAPSHOT
Define value for package: : war
Confirm properties configuration:
groupId: com.company
artifactId: myapp
version: 1.0-SNAPSHOT
package: war
 Y: : Y
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating OldArchetype: appfuse-basic-struts:2.0
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: com.company
[INFO] Parameter: packageName, Value: war
[INFO] Parameter: basedir, Value: /Users/mraible
[INFO] Parameter: package, Value: war
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: artifactId, Value: myapp
...{suppressed hundreds of Velocity warnings}...
[INFO] OldArchetype created in dir: /Users/mraible/myapp
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 43 seconds
[INFO] Finished at: Sat Feb 09 14:39:11 MST 2008
[INFO] Final Memory: 7M/511M
[INFO] ------------------------------------------------------------------------
powers:~ mraible$
&lt;/pre&gt;
&lt;p&gt;There&apos;s some typos (duplicate colons) in the prompts, but this is an alpha release, so I don&apos;t see any problem with that. I wonder where this list of archetypes is stored? We need to change the default version of AppFuse from 2.0 to 2.0.1.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/re_why_grails_doesn_t</guid>
    <title>RE: Why Grails doesn&apos;t use Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/re_why_grails_doesn_t</link>
        <pubDate>Wed, 16 Jan 2008 10:49:35 -0700</pubDate>
    <category>Java</category>
    <category>grails</category>
    <category>maven</category>
            <description>Graeme Rocher&apos;s in &lt;a href=&quot;http://graemerocher.blogspot.com/2008/01/why-grails-doesnt-use-maven.html&quot;&gt;Why Grails doesn&apos;t use Maven&lt;/a&gt;:
&lt;p class=&quot;quote&quot;&gt;
In his post entitled &lt;a href=&quot;http://jonasfagundes.com/blog/2008/01/grails-the-good-the-ugly-and-the-bad&quot;&gt;&quot;Grails - The Good, The Bad and the Ugly&quot;&lt;/a&gt;, Jonas has some nice praise for &lt;a href=&quot;http://grails.org/&quot;&gt;Grails&lt;/a&gt;, his main beef is that it is not built on Maven.&lt;br/&gt;&lt;br/&gt;So I wanted to clarify why exactly we chose not use &lt;a href=&quot;http://maven.apache.org/&quot;&gt;Maven&lt;/a&gt; (by default) and the explanation is there for all to see in Jonas&apos; first example of creating a Grails application vs creating a Maven project:&lt;br/&gt;&lt;br/&gt;Instead of&lt;br/&gt;&lt;code&gt;&lt;br/&gt;grails create-app name&lt;br/&gt;&lt;/code&gt;&lt;br/&gt;could be just&lt;br/&gt;&lt;code&gt;&lt;br/&gt;mvn archetype:create -U\&lt;br/&gt;-DarchetypeGroupId=net.liftweb\&lt;br/&gt;-DarchetypeArtifactId=lift-archetype-blank\&lt;br/&gt;-DarchetypeVersion=0.4\&lt;br/&gt;-DremoteRepositories=http://scala-tools.org/repo-releases\&lt;br/&gt;-DgroupId=your.proj.gid -DartifactId=your-proj-id&lt;br/&gt;&lt;br/&gt;&lt;/code&gt;My goodness, what a mouthful the Maven example is. There is a common acronym in the open source world called RTFM (read the *ing manual), when a user asks a question on a mailing list and the &quot;experts&quot; respond by pointing them to the place in the manual.
&lt;/p&gt;
&lt;p&gt;
I think Maven&apos;s biggest problems are 1) poor metadata in the central repository and 2) the source of metadata in projects (pom.xml).
&lt;/p&gt;
&lt;p&gt;
I believe #1 can be fixed if the Maven guys allow dependencies to be fixed based on user feedback. It&apos;s also gotten a lot better in recent years. In reality, maintaining transitive dependencies is hard and I believe Maven has done a good job. In reality, they&apos;re the only ones that slurp up transitive dependencies, so the only other option is to maintain the dependencies yourself.
&lt;/p&gt;
&lt;p&gt;
To fix #2, I think the problem is mainly XML and the verboseness of the elements-only pom.xml that Maven requires. Most of the contents of a pom.xml are either dependencies, plugins or exclusions/variances of Maven&apos;s conventions. What if Maven&apos;s metadata was pluggable? What if XML was only one option? What if you could write a pom.groovy and describe your entire build process in 5 lines instead of 500? &lt;em&gt;That&lt;/em&gt; would be very cool.&lt;/p&gt;
&lt;p&gt;I&apos;m still a Maven fan, mostly because it&apos;s greatly simplified the maintenance of and releasing of &lt;a href=&quot;http://appfuse.org&quot;&gt;AppFuse&lt;/a&gt;. When I do GWT, Seam or Grails development in the future, you can be sure I&apos;ll try to use Maven to do the development. Why? Because I&apos;ve learned how to use it and I don&apos;t feel the pain that so many others talk about. I also think it really shines on really large projects (builds that produce 30+ WARs for example). An Ant-based system on really large projects can become quite burdensome and difficult to maintain. Not only that, but it&apos;s very difficult to maintain a modular build system (where you can build/test/deploy a single WAR) with Ant. In my experience, really large Ant-based systems take forever to process that everything is up-to-date whereas Maven systems depend on each other and require you to keep them up to date. Sure it requires you to be smarter and run &quot;mvn install&quot; on your subprojects, but I&apos;d rather do that than wait 5 minutes for Ant to process everything just to run a test.
&lt;/p&gt;
&lt;p&gt;You might remember that the main reason I &lt;a href=&quot;http://raibledesigns.com/rd/entry/re_why_use_maven&quot;&gt;used to prefer Ant over Maven&lt;/a&gt; was speed. That was in Maven 1 days. With Maven 2, speed is no longer a problem and I&apos;ve found it much easier to run &quot;mvn jetty:run&quot; than &quot;ant deploy&quot; and wait for Tomcat to restart. IMO, the perfect development environment is one were you can run a command-line command (or use your IDE to start the server) and code away without worrying about restarts. Seam and Grails offer this environment, but it&apos;s unlikely your entire organization is going to use standardize on those frameworks and not have anything else. I think Maven and the Maven Jetty Plugin offer a nice alternative for the rest of those applications.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/upgrading_appfuse_to_spring_2</guid>
    <title>Upgrading AppFuse to Spring 2.5</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/upgrading_appfuse_to_spring_2</link>
        <pubDate>Wed, 7 Nov 2007 08:27:20 -0700</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>appfuse</category>
    <category>spring</category>
            <description>Last night, I spent a few minutes upgrading AppFuse to &lt;a href=&quot;http://www.springframework.org/node/548&quot;&gt;Spring 2.5 RC1&lt;/a&gt;. According to InfoQ, &lt;a href=&quot;http://www.infoq.com/news/2007/11/spring25rc&quot;&gt;Spring 2.5 is a drop-in upgrade for Spring 2.0&lt;/a&gt;. However, if you&apos;re using Maven, it&apos;s not quite that easy. The good news is it is easy, you just need to change your pom.xml a bit. The steps I used to upgrade AppFuse are listed below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Add a repository for Spring&apos;s milestone releases:
&lt;pre style=&quot;margin-top: 5px&quot;&gt;
&amp;lt;repository&amp;gt;
    &amp;lt;id&amp;gt;spring-milestone&amp;lt;/id&amp;gt;
    &amp;lt;url&amp;gt;http://s3.amazonaws.com/maven.springframework.org/milestone&amp;lt;/url&amp;gt;
&amp;lt;/repository&amp;gt;
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Change artifactId of &quot;spring-mock&quot; to be &quot;spring-test&quot;.&lt;/li&gt;
&lt;li&gt;Change version to be 2.5-rc1.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point, if you&apos;re using &quot;spring&quot; as your artifactId (instead of the smaller fine-grained dependencies), you&apos;ll likely get the following error in a Spring MVC application:&lt;/p&gt;
&lt;pre&gt;
java.lang.NoClassDefFoundError: 
org/springframework/web/servlet/handler/AbstractUrlHandlerMapping
&lt;/pre&gt;
&lt;p&gt;This happens because Spring MVC is no longer included in the uber spring.jar. You&apos;ll need to add a dependency on &quot;spring-webmvc&quot; to solve this problem. Unfortunately, this JAR is dependent on the fine-grained modules, so you may have to modify your pom.xml to depend on the fine-grained modules - or exclude them all from spring-webmvc.
&lt;/p&gt;
&lt;p&gt;The good news is Spring has excluded all the &lt;a href=&quot;http://raibledesigns.com/rd/entry/maven_2_hates_commons_logging&quot;&gt;invalid commons-logging dependencies&lt;/a&gt; for you so you don&apos;t have to anymore.
&lt;/p&gt;
&lt;p&gt;After getting all the dependencies straightened out - I ran the integration tests:
&lt;/p&gt;
&lt;pre&gt;
org.springframework.beans.NotReadablePropertyException: Invalid property 
&apos;fileUpload&apos; of bean class [org.appfuse.webapp.controller.FileUpload]: Bean 
property &apos;fileUpload&apos; is not readable or has an invalid getter method: Does the 
return type of the getter match the parameter type of the setter?
&lt;/pre&gt;
&lt;p&gt;
Looking at uploadForm.jsp, I&apos;m guessing the problem happens because of the following code:
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;spring:bind path=&quot;fileUpload.file&quot;&amp;gt;
&amp;lt;input type=&quot;file&quot; name=&quot;file&quot; id=&quot;file&quot; class=&quot;file medium&quot; value=&quot;&amp;lt;c:out value=&quot;${status.value}&quot;/&amp;gt;&quot;/&amp;gt;
&amp;lt;/spring:bind&amp;gt;
&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;http://opensource.atlassian.com/projects/spring/browse/SPR-4022&quot;&gt;Confirmed&lt;/a&gt; - changing the &quot;path&quot; attribute to &quot;file&quot; fixes the problem. I also found out that setting the &quot;value&quot; on an &amp;lt;input type=&quot;file&quot;&amp;gt; doesn&apos;t work, so wrapping the field with &amp;lt;spring:bind&amp;gt; doesn&apos;t make a whole lot of sense anyway.&lt;/p&gt;
&lt;p&gt;To conclude, it doesn&apos;t look like the first release candidate of Spring 2.5 is &lt;em&gt;exactly&lt;/em&gt; a drop-in upgrade for Spring 2.0, but it&apos;s pretty darn close. I&apos;m sure by the time it&apos;s released, it will be. I&apos;d encourage you to try 2.5 in your Spring-dependent projects to see if you find any issues.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; I was successfully able to migrate AppFuse from using the uber JAR to fine-grained JARs. However, I ran into a couple issues in the process. The first is that even though I&apos;m including spring-aop in the &lt;em&gt;appfuse-service&lt;/em&gt; module, it&apos;s not pulled in for the web frameworks (which depend on appfuse-service). Explicitly declaring spring-aop as a dependency for the appfuse-web module fixes this. Secondly, I had to modify my Acegi Security exclusions  so it wouldn&apos;t include dependencies that no longer exist in 2.5.
&lt;/p&gt;
&lt;pre&gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.acegisecurity&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;acegi-security-tiger&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;${acegi.version}&amp;lt;/version&amp;gt;
    &amp;lt;exclusions&amp;gt;
        &amp;lt;exclusion&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-dao&amp;lt;/artifactId&amp;gt;
        &amp;lt;/exclusion&amp;gt;
        &amp;lt;exclusion&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-jdbc&amp;lt;/artifactId&amp;gt;
        &amp;lt;/exclusion&amp;gt;
        &amp;lt;exclusion&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-remoting&amp;lt;/artifactId&amp;gt;
        &amp;lt;/exclusion&amp;gt;
        &amp;lt;exclusion&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-support&amp;lt;/artifactId&amp;gt;
        &amp;lt;/exclusion&amp;gt;
    &amp;lt;/exclusions&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/pre&gt;
&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/flex_and_grails_made_easy</guid>
    <title>Flex and Grails Made Easy</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/flex_and_grails_made_easy</link>
        <pubDate>Thu, 1 Nov 2007 23:00:38 -0600</pubDate>
    <category>Java</category>
    <category>idea</category>
    <category>grails</category>
    <category>maven</category>
    <category>flex</category>
            <description>I love how easy it is to start new projects these days. It was very difficult when I started creating AppFuse way back in 2002. &lt;em&gt;We&apos;ve come a long way baby!&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;Here&apos;s a couple of easy ways to get started with Flex and Grails:&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://ancientprogramming.blogspot.com/2007/11/quickstart-flex-development-with-this.html&quot;&gt;Quickstart flex development with this maven archetype&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://docs.codehaus.org/display/GRAILS/IDEA+Integration&quot;&gt;Grails development in IntelliJ IDEA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope to develop with Flex, Grails, GWT or YUI + Struts 2 in the next 6 months. These seem like the most exciting technologies for Java web development in 2008. </description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/maven_meetup_in_san_francisco</guid>
    <title>Maven Meetup in San Francisco tomorrow (Tuesday)</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/maven_meetup_in_san_francisco</link>
        <pubDate>Mon, 8 Oct 2007 22:55:41 -0600</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>meetup</category>
            <description>If you live in the Bay Area and you&apos;re interested in talking with the inventors of Maven and/or XWiki, you should checkout the &lt;a href=&quot;http://blogs.codehaus.org/people/vmassol/archives/001618_xwiki_maven_meetup.html&quot;&gt;XWiki + Maven meetup&lt;/a&gt; at Terracotta&apos;s HQ. Java Open Source gurus Vincent Massol and Jason van Zyl will be there - sounds like a fun event!</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/live_coding_for_4_days</guid>
    <title>Live Coding for 4 Days Straight</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/live_coding_for_4_days</link>
        <pubDate>Thu, 24 May 2007 13:50:30 -0600</pubDate>
    <category>Java</category>
    <category>java</category>
    <category>spring</category>
    <category>selenium</category>
    <category>maven</category>
    <category>dbunit</category>
    <category>ant</category>
            <description>Last week I had an interesting 4-day consulting gig for a client in Boulder.  I was supposed to fly out to Connecticut to deliver a training course, but it got rescheduled due to the 45-day Vendor Approval Process I need to go through. The client in Boulder wanted me to come out and do an architectural assessment and provide recommendations. Topics they were interested in: web tier (specifically Spring MVC), Security, Ajax integration, build process, web services and localization. I&apos;ve done this kind of before with Virtuas, but this time was different. With Virtuas, I&apos;d do 5-days worth of presentations on just about anything the customer wanted. For example, checkout &lt;a href=&quot;http://static.raibledesigns.com/repository/text/JavaWebTechnologiesAgenda.pdf&quot;&gt;this agenda&lt;/a&gt; for a client in NY last year.
&lt;br/&gt;&lt;br/&gt;
With the company in Boulder, I delivered zero presentations. Instead, everything we talked about and coded was hands-on. On Tuesday, we started out by discussing their application and some issues they were having. They&apos;d done a lot of customization to Spring MVC and had managed to eliminate all the XML needed when adding new controllers and views. I spent 3-4 hours that day with 2 of their engineers finalizing and implementing their convention-over-configuration rules. On Wednesday, I helped them implement Acegi Security into their application.  This was interesting because they didn&apos;t have any security mechanism and we had to implement Acegi from scratch and then tie it into their backend (using a custom AuthenticationProvider).  We also integrated i18n so all messages were retrieved from their database.
&lt;br/&gt;&lt;br/&gt;
On Thursday, we configured Ant to run their tests and wrote some tests for their controllers. As part of this process, I showed them how to use jMock and EasyMock and tried to explain the benefits of using Spring IoC (which they still aren&apos;t sold on). On Friday, we integrated Selenium into their build process and wrote a few tests using Selenium&apos;s Java support. In the afternoon, I showed them how they might use Scriptaculous and Prototype to Ajax-enable some features in their application.
&lt;br/&gt;&lt;br/&gt;
Doing all the &quot;live coding&quot; on someone else&apos;s machine (with 5 developer&apos;s watching) was a bit nerve wracking. However, thanks to Cenqua&apos;s &lt;a href=&quot;http://www.cenqua.com/fisheye/&quot;&gt;FishEye&lt;/a&gt; tool, I was able to search &lt;a href=&quot;http://fisheye4.cenqua.com/browse/appfuse&quot;&gt;AppFuse&lt;/a&gt; and &lt;a href=&quot;http://fisheye4.cenqua.com/browse/appfuse-light&quot;&gt;AppFuse Light&apos;s&lt;/a&gt; SVN repositories for code snippets and examples. While I knew how to do much of the stuff we covered, FishEye and Google bailed me out when I didn&apos;t. About halfway through, I realized that I don&apos;t keep a lot of my knowledge in my head. Instead, it&apos;s on this blog, or spread out on the web. I don&apos;t remember URLs anymore, all I remember are keywords. If I&apos;ve read a blog post or article on the web, chances are I can find it again pretty easily with Google. Even though I store a lot of bookmarks in del.icio.us, I didn&apos;t use it all week. Remembering keywords is the new bookmark for me.
&lt;br/&gt;&lt;br/&gt;
The whole week was an interesting exercise in &quot;live coding.&quot; The whole team (6 or so) sat in a conference room all week and VNC&apos;ed into the architect&apos;s box to do the work. We worked in Eclipse and used WTP to deploy/test things on Tomcat. The keyboard was passed around between developers at random and everyone got a chance to implement new features. I think the reason that everything worked so well was because the team was full of Senior Java Developers. Everyone learned from each other as they saw new shortcuts, keystrokes and ways or writing code. I don&apos;t know if this kind of thing will work in all development teams, but I&apos;d encourage you to try it. It&apos;s a great way to share knowledge and educate the entire team on how a new module works.
&lt;br/&gt;&lt;br/&gt;
Over the weekend, I received the following e-mail from one of the developers on the team:&lt;/p&gt;
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
Very nice to meet you this past week and get a chance to see firsthand the breadth and depth of your experience in web app frameworks and such. I believe due to your visit, we will be cranking happily along here very shortly. Everyone was quite happy with the results at the end of the day yesterday.
&lt;/p&gt;
&lt;p&gt;
On a related note, if you&apos;re looking to hire an enthusiastic Web + Java Developer, please take a look at &lt;a href=&quot;http://raibledesigns.com/resume.jsp&quot;&gt;my resume&lt;/a&gt; or &lt;a href=&quot;http://raibledesigns.com/contact.jsp&quot;&gt;send me an e-mail&lt;/a&gt;. My current contract ends this month and I&apos;m hoping to find something new to get me through the summer.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/sonatype_a_new_company_around</guid>
    <title>Sonatype - a new company around Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/sonatype_a_new_company_around</link>
        <pubDate>Wed, 18 Apr 2007 09:19:21 -0600</pubDate>
    <category>Java</category>
    <category>maven</category>
            <description>From &lt;a href=&quot;http://blogs.maven.org/jvanzyl/2007/04/18/1176905394766.html&quot;&gt;Jason van Zyl&apos;s Maven Diaries&lt;/a&gt;:
&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
&lt;span style=&quot;text-align: center; display: block; margin-bottom: 10px&quot;&gt;
&lt;a href=&quot;http://sonatype.com&quot;&gt;&lt;img src=&quot;//static.raibledesigns.com/repository/images/sonatype-logo.png&quot; width=&quot;357&quot; height=&quot;53&quot; alt=&quot;Sonatype&quot; style=&quot;border: 0&quot; /&gt;&lt;/a&gt;
&lt;/span&gt;
Since my departure from Mergere I&apos;ve been quietly and steadily working to help start a  Maven related company that I&apos;m proud to say I&apos;m a part of. No grandiose launch, no marketing hype, no VCs, haven&apos;t talked to a single analyst, and we hope that you can actually understand what we do by looking at our website. The company&apos;s name is &lt;a href=&quot;http://www.sonatype.com&quot;&gt;Sonatype&lt;/a&gt; and I&apos;m finally happy with the &lt;a href=&quot;http://www.sonatype.com/about.html&quot;&gt;people&lt;/a&gt; involved and the direction we&apos;re headed in. We are focused on facilitating the adoption of Maven through our &lt;a href=&quot;http://www.sonatype.com/partners/partners.html&quot;&gt;partners network&lt;/a&gt;, providing training, and delivering Maven related products for software development.
&lt;/p&gt;
&lt;p&gt;Having &lt;a href=&quot;http://mergere.com&quot;&gt;two&lt;a&gt; &lt;a href=&quot;http://www.sonatype.com&quot;&gt;companies&lt;/a&gt; wrapped around Maven can&apos;t be a bad thing. However, let&apos;s hope Sonatype has some funding to pay folks to work on the project more, rather than other products that may or may not be successful.
&lt;br/&gt;&lt;br/&gt;
Two things that could make this company very well liked in the open source community:&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;&lt;strong&gt;Clean up the Maven Repository&lt;/strong&gt;: Add/delete/modify as requested by users. There&apos;s other projects using the repo now and even folks &lt;a href=&quot;http://www.1060.org/blogxter/entry?publicid=EAF9A3AEADAC7A115B6A3C4DE8A5E2EE&quot;&gt;campaigning&lt;/a&gt; against Maven. If Maven folks are responsible for cleaning it up, they&apos;ll be heroes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provide repository statistics&lt;/strong&gt;: A lot of open source projects like to track their download statistics. It&apos;s a metric for measuring success (in addition to mailing list traffic). If they move to a full Maven-based distribution model (like AppFuse is), there&apos;s no more statistics.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Are there other things you think Sonatype can do to make Maven easier to use and more successful?
&lt;br/&gt;&lt;br/&gt;
Congrats to &lt;a href=&quot;http://www.sonatype.com/about.html&quot;&gt;Neel, Jason, John, Kenney, Andrew, Eric and Eirik&lt;/a&gt;. I hope you succeed in your mission. I think w/o the VCs and the get-rich-quick folks, it should be a lot easier. Cash isn&apos;t always the key indicator of success - more often happiness and job satisfaction are.</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/ant_vs_maven</guid>
    <title>Ant vs. Maven</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/ant_vs_maven</link>
        <pubDate>Mon, 16 Apr 2007 11:26:13 -0600</pubDate>
    <category>Java</category>
    <category>ant</category>
    <category>appfuse</category>
    <category>maven</category>
            <description>I found a good post from Steve Loughran on &lt;a href=&quot;http://www.1060.org/blogxter/entry?publicid=9EE3794599F42C4E1D9BF2F2FE655180&quot;&gt;what&apos;s wrong with Maven&apos;s repositories&lt;/a&gt;. I agree with most of his points, but would like to point out &lt;a href=&quot;http://mvnrepository.com/&quot;&gt;mvnrepository.com&lt;/a&gt;. This site seems to provide good XML Feeds for what&apos;s been uploaded to Maven&apos;s Central Repository. If you&apos;re using Maven, you should probably subscribe to its &lt;a href=&quot;http://mvnrepository.com/feeds/atom.xml&quot;&gt;Atom Feed&lt;/a&gt;.
&lt;br/&gt;&lt;br/&gt;
In related news, Timothy M. O&apos;Brien has an entry about &lt;a href=&quot;http://www.oreillynet.com/onjava/blog/2007/04/upcoming_book_ant_in_action_1.html&quot;&gt;Steve&apos;s upcoming book: Ant in Action&lt;/a&gt;. This book is the 2nd edition of &lt;a href=&quot;http://www.manning.com/hatcher/&quot;&gt;Java Development with Ant&lt;/a&gt;. I have a hard time believing Erik Hatcher is helping Steve write Ant in Action - AFAIK, he&apos;s off in Rails-land enjoying himself. Regardless, I&apos;m sure Ant in Action will be an excellent book. Java Development with Ant is one of my favorite technical books of all time and is largely responsible for inspiring me to write &lt;a href=&quot;http://appfuse.org&quot;&gt;AppFuse&lt;/a&gt;. I read JDwA way back in October 2002 and used a lot of its code to develop AppFuse 1.x&apos;s Ant-based build system.&lt;br/&gt;&lt;br/&gt;
Like Tim, I still like Ant. However, AppFuse 2.x uses Maven 2 and most of the projects I work on these days use Maven 2. It may surprise some folks, but I actually like Maven 2 (not Maven 1). Sure it has issues, but after a year of using it in anger, I know how to solve most of its quirks. AppFuse 2.x users will benefit from this greatly and I&apos;m thinking of changing its tagline to &quot;We make Maven work.&quot; &lt;img src=&quot;https://raibledesigns.com/images/smileys/wink.gif&quot; class=&quot;smiley&quot; alt=&quot;;-)&quot; title=&quot;;-)&quot; /&gt;
&lt;br/&gt;&lt;br/&gt;
One of the most interesting things about moving to Maven is we were easily able to make AppFuse more like a framework than a project starter kit.  We &lt;em&gt;thought&lt;/em&gt; this is what most folks wanted - especially the ability to upgrade a project to the latest version of AppFuse. While &lt;em&gt;some&lt;/em&gt; folks wanted this, it seems like &lt;em&gt;most&lt;/em&gt; folks liked the full-source version that was a pain-in-the-ass to upgrade. I don&apos;t blame them. On the project I&apos;m on, I&apos;ll likely be converting to a full-source version before the project is over. That&apos;s why &lt;a href=&quot;http://issues.appfuse.org/browse/APF-675&quot;&gt;APF-675&lt;/a&gt; exists. I doubt we&apos;ll make it happen for the 2.0 final release, but it &lt;em&gt;is&lt;/em&gt; on our radar of things to do shortly after. With any luck, we&apos;ll create a way to migrate projects using embedded AppFuse to full-source AppFuse.
&lt;br/&gt;&lt;br/&gt;
I&apos;d also like to point out something ironic. With AppFuse 1.x, there were a &lt;em&gt;lot&lt;/em&gt; of folks that advocated we move to Maven. Their primary reasoning - the Ant build scripts were too long and complicated. How about a good ol&apos; lines of XML comparison for those folks:
&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;Lines of Ant-related XML in AppFuse 1.x: 1655&lt;/li&gt;
&lt;li&gt;Lines of Maven-related XML in AppFuse 2.x: 2847&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oh wait, that&apos;s not a fair comparison. The above number is for AppFuse in SVN, which end users won&apos;t deal with. A new project created with AppFuse 2.x will likely have a pom.xml with 634 lines. That&apos;s about 1/3 of the amount needed for Ant in AppFuse 1.x. Maven hasn&apos;t exactly gotten us away from XML hell though. How about a LOC count for archetypes vs. installers:&lt;/p&gt;
&lt;ul class=&quot;glassList&quot;&gt;
&lt;li&gt;Lines of Ant-related XML for AppFuse 1.x framework installers: 2786&lt;/li&gt;
&lt;li&gt;Lines of Maven-related XML for AppFuse 2.x archetypes (including archetype&apos;s pom.xml files): Too much to count. Creating archetypes is &lt;em&gt;waayyyy&lt;/em&gt; too complicated IMO. Basic archetypes seem to be around 740 lines (pom.xml for archetype project, archetype.xml and archetype&apos;s pom.xml), modular archetypes are around 870. 740 x 4 + 870 x 4 = 6440. I&apos;m guessing the full-source archetypes will add another 5000 lines of XML. Ugh.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This XML-for-archetypes comparison might be unfair as well. With 1.x, you could only create a webapp, with 2.x, you can create a modular application and chop off the web-portion if you so choose.&lt;/p&gt;
&lt;p&gt;
Of course, the real benefits of moving to Maven are elsewhere. We&apos;ve seen quite an uptick on the mailing list in the last few months. There&apos;s &lt;a href=&quot;http://candy4appfuse.sf.net&quot;&gt;tools cropping up&lt;/a&gt; and I&apos;ve gotten quite a few inquiries about training (yes, I do have a 3-day course on Spring, Hibernate, Ajax, Maven and AppFuse). To me, AppFuse 2.x seems more complicated than 1.x, but it seems the community thinks otherwise. Judging from the increased amount of developer activity on the project, developers seem more interested in a Maven-based system too. Then again, we are &lt;em&gt;making Maven work!&lt;/em&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/re_jetty_ant_plugin</guid>
    <title>RE: Jetty Ant Plugin</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/re_jetty_ant_plugin</link>
        <pubDate>Thu, 8 Mar 2007 08:13:08 -0700</pubDate>
    <category>Java</category>
    <category>maven</category>
    <category>jetty</category>
    <category>ant</category>
            <description>It looks like &lt;a href=&quot;http://blogs.webtide.com/janb/2007/03/08/1173333129817.html&quot;&gt;Jetty has a new Plugin for Ant&lt;/a&gt;. If you&apos;ve used the &lt;a href=&quot;http://www.mortbay.org/maven-plugin/index.html&quot;&gt;Jetty Maven Plugin&lt;/a&gt;, you know this is a slick way to quickly deploy your application. For those of you wondering about Tomcat, there&apos;s a similar &lt;a href=&quot;http://mojo.codehaus.org/tomcat-maven-plugin/introduction.html&quot;&gt;Tomcat Maven Plugin&lt;/a&gt; that supports tomcat:run and tomcat:run-war.  However, it&apos;s still in Mojo&apos;s sandbox.
&lt;br/&gt;&lt;br/&gt;
I&apos;m pumped to see this Jetty task for Ant because I&apos;ve been thinking a lot about creating an &lt;a href=&quot;http://issues.appfuse.org/browse/APF-675&quot;&gt;exploded, full-source archetype for AppFuse 2.0&lt;/a&gt;. Of course, it&apos;s probably possible to start Jetty and monitor your project for changes w/o this task - but it does seem to make things a fair amount easier. If we do a full-source archetype, it makes sense to support Ant as well - especially since we can probably re-use the build.xml from AppFuse Light. 
&lt;br/&gt;&lt;br/&gt;
This brings up a related questions I &lt;a href=&quot;http://www.nabble.com/Questions-for-2.x%3A-Archetypes-and-UI-Testing-tf3364157s2369.html&quot;&gt;asked on the AppFuse mailing list&lt;/a&gt; yesterday:&lt;/p&gt;
&lt;p class=&quot;quote&quot;&gt;
A couple of questions for folks using (or planning to use) 2.x:
&lt;br/&gt;&lt;br/&gt;
1. As far as archetypes go, are you using basic or modular?
&lt;br/&gt;&lt;br/&gt;
2. If there was a 3rd type of archetype that included the full source (like AppFuse 1.x), would you use it over the existing basic or modular archetypes?  If yes, I&apos;m assuming upgrading is not that big of an issue for you?
&lt;/p&gt;
&lt;p&gt;If you&apos;ve tried AppFuse 2.x and would like to answer these questions, please add a comment.&lt;/p&gt;
&lt;p style=&quot;font-style: italic&quot;&gt;There&apos;s another questions about Selenium vs. Canoo WebTest in that post, but that&apos;s reserved for another entry where I&apos;ll talk about Selenium options in Maven 2.&lt;/p&gt;
&lt;p&gt;</description>          </item>
    <item>
    <guid isPermaLink="true">https://raibledesigns.com/rd/entry/artifactory_a_new_maven_2</guid>
    <title>Artifactory - a new Maven 2 Repository Manager for Enterprises</title>
    <dc:creator>Matt Raible</dc:creator>
    <link>https://raibledesigns.com/rd/entry/artifactory_a_new_maven_2</link>
        <pubDate>Mon, 5 Mar 2007 07:35:00 -0700</pubDate>
    <category>Java</category>
    <category>artifactory</category>
    <category>nexus</category>
    <category>maven</category>
            <description>From the &lt;a href=&quot;http://www.nabble.com/-ANN--Artifactory---new-Maven-2-proxy-repository-tf3344299s177.html#a9301347&quot;&gt;Maven 2 user list&lt;/a&gt;:
&lt;/p&gt;
&lt;p class=&quot;quote&quot; style=&quot;color: #666; margin-left: 10px&quot;&gt;
We would like to announce the immediate availability of Artifactory, a Maven 2 enterprise proxy.
&lt;br/&gt;&lt;br/&gt;
Artifactory offers advanced proxying, caching and security facilities to answer the needs of a robust, reproducible and independent build environment using Maven 2.
It uses a JSR-170 Java Content Repository (JCR) for storage, which makes it extremely easy to manage searchable metadata, and provide extended features such as security, transacted operations, auditing, locking, etc.
&lt;br/&gt;&lt;br/&gt;
Artifactory is distributed under APLv2 at &lt;a href=&quot;http://artifactory.sourceforge.net&quot;&gt;http://artifactory.sourceforge.net&lt;/a&gt;. It is currently available as a downloadable archive, that can be run out of the box (with default settings). An install script to run it as a Linux service is also provided. A (limited) guest live demo is available at &lt;a href=&quot;http://www.jfrog.org/artifactory/&quot;&gt;http://www.jfrog.org/artifactory&lt;/a&gt; (username/password is guest/guest).
&lt;br/&gt;&lt;br/&gt;
You are welcome to give it a go!
&lt;br/&gt;&lt;br/&gt;
Cheers,
&lt;br/&gt;&lt;br/&gt;
Yoav Landman,&lt;br/&gt;
The Artifactory Team &lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;So how does this compare to &lt;a href=&quot;http://maven.apache.org/archiva/&quot;&gt;Archiva&lt;/a&gt;, &lt;a href=&quot;http://proximity.abstracthorizon.org/&quot;&gt;Proximity&lt;/a&gt; and &lt;a href=&quot;http://maven-proxy.codehaus.org/&quot;&gt;Maven Proxy&lt;/a&gt;? One user &lt;a href=&quot;http://www.nabble.com/-ANN--Artifactory---new-Maven-2-proxy-repository-tf3344299s177.html#a9308827&quot;&gt;writes&lt;/a&gt; (formatted for better reading):&lt;/p&gt;
&lt;div class=&quot;quote&quot; style=&quot;color: #666; margin-left: 10px; margin-bottom: 10px&quot;&gt;
My experience so far:
&lt;ul class=&quot;glassList&quot; style=&quot;margin-top: 10px&quot;&gt;
&lt;li&gt;&lt;strong&gt;Archiva:&lt;/strong&gt; Alpha; doesn&apos;t work (random webdav deployment failures), loads of bugs, low rate of progress. Feels dead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proximity:&lt;/strong&gt; Works; slightly confusing (don&apos;t like the separation of metadata); lots of new releases constantly; hard to configure (hacking around with spring config files) - our install takes *forever* to restart.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;m2proxy&lt;/strong&gt;: simple, but simple.&lt;/li&gt;
&lt;/ul&gt;
Fingers crossed that artifactory hits the sweet spot...
&lt;/div&gt;
&lt;p&gt;It&apos;s interesting to see that Artifactory&apos;s UI is powered by Wicket and Dojo. The demo seems kind of sluggish, but I don&apos;t believe this application is meant to handle more than 10 users at a time. For more information on Artifactory&apos;s features, see its &lt;a href=&quot;http://www.jfrog.org/sites/artifactory/latest/introduction.html&quot;&gt;introduction page&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;It&apos;s great to see a (seemingly) good tool come out for internal repository management. 
&lt;br/&gt;&lt;br/&gt;
I spent a couple days last week analyzing the best open source continuous integration server for Maven 2 projects. &lt;a href=&quot;http://hudson.dev.java.net&quot;&gt;Hudson&lt;/a&gt; turned out to be the clear winner with the best UI and easiest setup. It also actually &lt;em&gt;worked&lt;/em&gt;, which is a lot more than I can say for Continuum. While I did get Continuum to work, it required turning on anonymous SVN (no, putting the username/password in the URL did &lt;em&gt;not&lt;/em&gt; work). CruiseControl worked as well, but required config.xml knowledge, which sometimes scares admins. Pulse and Bamboo continue to be the best commercial Maven 2 testers, while TeamCity failed my 10-minute test (twice!). One of the features I was looking for was &lt;a href=&quot;http://trac.edgewall.org/&quot;&gt;Trac&lt;/a&gt; integration and that only exists for &lt;a href=&quot;https://oss.werkbold.de/trac-cc&quot;&gt;CruiseControl&lt;/a&gt; and &lt;a href=&quot;http://dev.rectang.com/projects/continutrac&quot;&gt;Continuum&lt;/a&gt;. 
&lt;br/&gt;&lt;br/&gt;
It&apos;s amazing to see projects like Continuum and Archiva. If they&apos;re any reflection of the Maven team&apos;s ability to develop software, that&apos;s frightening. My advice: discontinue both of these projects as they&apos;re a waste of anyone&apos;s time to even research them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update October 2009:&lt;/strong&gt; Fast forward a couple years and I take back what I said about the Maven&apos;s team ability to develop good software. &lt;a href=&quot;http://raibledesigns.com/rd/entry/nexus_is_a_kick_ass&quot;&gt;Nexus is a kick-ass Repository Manager&lt;/a&gt;.</description>          </item>
  </channel>
</rss>