Last week, I posted a thread titled Maven Skepticism to the WOProject list. It was about my misgivings about Maven, and the issues I was having getting started with it.
So the last few days I've been playing with Maven.
I am no longer skeptical.
So I thought I would post about my newfound optimism with Maven. I feel I owe it to Henrique and Lachlan for their help. (Thanks guys) I also think the current maven evangelism documentation is written a little too formally to be comprehensive.
Background:
I've been programming since I was 12, which means nearly 30 years now. I have a saying:
Every generation thinks they invented sex, and every generation tries to reinvent make.
Consequently, I hate Ant. I think its implementation is completely fubar. I've ranted about it before. I also hate our current build process at work, which is basically to hope/pray that the ant build we do nightly for deployment/packaging matches the developer builds we do in Eclipse.
Now that I've finally gotten my team on svn, its time to fix the build process and reorganize our projects. Hence the interest in Maven, basically precipitated by Apple publishing their nightly builds as a Maven repository.
To get started with Maven, I sat down with the Wonder sources, and tweaked the existing pom.xml files that had been broken since the great re-org to work. (pom.xml are the only and only type of file that Maven uses for building)
What I found:
Maven is a lot closer to how I would design a build system then it is to Ant. In that, its a lot more similar to how typical modern IDEs work: If Maven sees a .java file in the right place, it will compile it and put in in the jar. If it sees a file in the right place, it will treat it as a resource file, and put it in the appropriate location.
In short, for most projects, you don't have to specify a bunch of stuff, you just have to put them in the right place. Additionally, unlike ant builds, there's very little redundant information in a maven pom file.
To give you some examples, for the current Wonder Ant builds, between build.xml files, generic.xml, build.properties files, .classpath and .patternset files, there are 5320 lines of build configuration information in the current Wonder build. The equivalent pom files are 2447 lines, which is not only more efficient, but includes more information to help avoid the jarmeggedon/jarhell problem.
Jarmeggedon/jarhell
It seems like one of the greatest tools in a Java programmers arsenal is Google, or rather, 3rd party libraries. If you look at the Wonder source, there are 65 different .jar files included, about 1 per project on average. Many of these jar files are duplicates of each other, or even worse, different versions of the same jar, like there is a version of commons-logging.jar in ERJGroupsSynchronizer and another one in EROpenID. Meanwhile, commons-logging is up to version 1.1.1.
To my way of thinking, the Wonder ant builds are already broken if EROpenID is building against commons-logging-1.03, but then deployed with 1.1.1...
Maven's solution goes by the fancy name of "dependency management". What that means in practice is that most of the information in the pom.xml is just a list of what other projects in your source tree a given project depends on, and what jars you need by name/version. In return, maven:
1. Finds and downloads any jars you're missing. 2. Finds and downloads any jars that those jars use! 3. Builds any inter-project dependencies. 4. Generates the correct classpath. 5. Packages jars as needed in the appropriate place. A dependency looks like the following:
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency>
Most of the pom.xml file consists of these dependencies, and the site http://mvnrepository.com will even generate them for you. Moreover, if you put a "dependencyManagement" section in your top level pom as follows:
<dependencyManagement>
<dependencies>
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency> Then you can leave out the version specifier for your individual projects entirely:
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </dependency>
Which means you only have to change a single file when you want to use version 1.1.2 or something.
It works unbelievably well. How well? Well, in the course of setting up pom.xml files for Wonder, I found out that Wonder was missing a secondary dependency, because it used a certain jar file, which used another jar file which wasn't included.
It's pretty cool when your build system can find bugs that otherwise you wouldn't have found until runtime.
Particularly Suited to WO
A minimal WO application ends up with the following structure:
BusinessLogic.framework (because its always a good idea to put the BL in a library so its shareable) App.woa (main user app) Admin.woa (because you have to be able to administer the damn thing)
So immediately, you now have 3 projects to build in order to deploy. That can mean 3 sets of jar files to keep track of, 3 classpaths to maintain. Even trickier, if a new jar is needed for BusinessLogic, you have to add that jar (and any jar that jar references!) to App and Admin.
With maven, you only need add the dependency to BusinessLogic.framework, and you don't need to dig up what jar that jar references because the maven repository will pull those in as well. You don't even have to remember to do it, because since maven is building the classpath for you, the compiler will automatically bitch when it sees things missing.
So I think maven is particularly suited to WO.
Summary
I have a ways to go with my maven knowledge, but given that I was able to get Wonder building without really knowing that much about mvn, and without knowing all the ins-outs of the Wonder interelationships, I think that speaks well for Maven.
Pierce |