I'm pleasantly surprised about Maven. For years I've said "I'll stop writing code before I learn another build tool" but I have to revise that after 10 days with Maven. Everything works as it should. Sure, the Maven design is not completely evil.. on the other hand I've heard and sometimes experienced in the past how bad the actual Maven code is. It seemed to me like there was always a quality problem attached to Maven and I've always had that bias confirmed. For example, when I could no longer build the project I was working on for years, because the lead developer decided to switch to Maven. I gave up after a few hours and haven't touched the project since, and from what I can tell, 3 years later there is still no generated Javadoc available.
Learning a new build tool is not going to make your application code better or helping you finish your work. It's an expense in time that might pay off later but right now you'd rather work on real problems than re-inventing the wheel. So starting with Maven now it was important to me to get more out of it, something that would have been difficult to do with Ant.
First, I'm surprised how well the dependency management stuff worked for me. Of course half of the projects I included as dependencies have broken transitive dependencies: Outdated POMs, references to local repositories, wrong scope, unnecessary dependencies that pull in 50 JARs, and so on. But I didn't expect anything else so that is easily fixed with exclusions and the occasional bug report.
I also want to use the 'site' lifecycle in Maven and I want it to generate my project's webpages. Like probably many other devs, I loathe the default reports generated by Maven. Nobody cares about your test code coverage. Nobody cares about your plugin dependencies. Stop using these reports as an excuse for missing real documentation. And, not only is the default template fugly, the generated menu navigation is also horrible and does not reflect what people look for on a software project website.
It turns out that the whole reporting API and implementation of Maven is really really bad code, with no documentation. You will find some guidelines on some random wikis that show you how to write a Maven report (site generation) plugin - which won't work. Not documenting their stuff seems to be how these developers avoid stabilizing their SPI/API.
Here is a Maven reporting plugin skeleton that works with whatever site plugin is the default in Maven 2.2.0:
/**
* @goal myreport
* @phase site
*/
public class MyReport extends AbstractMavenReport {
/**
* @parameter expression="${project}"
* @required
* @readonly
*/
protected MavenProject project;
@Override
protected MavenProject getProject() {
return project;
}
// Not used by Maven site plugin but required by API!
@Override
protected Renderer getSiteRenderer() {
return null; // Nobody calls this!
}
// Not used by Maven site plugin but required by API!
// (The site plugin is only calling getOutputName(), the output dir is fixed!)
@Override
protected String getOutputDirectory() {
return null; // Nobody calls this!
}
// Abused by Maven site plugin, a '/' denotes a directory path!
public String getOutputName() {
String path = "someDirectoryInTargetSite/canHaveSubdirectory/OrMore";
String outputFilename = "some-file";
// The site plugin will make the directory (and regognize the '/') in the path,
// it will also append '.html' onto the filename and there is nothing (yes, I tried)
// you can do about that. Feast your eyes on the code that instantiates
// this (good luck finding it):
// org.apache.maven.doxia.module.xhtml.decoration.render.RenderingContext
return path + "/" + outputFilename;
}
public String getName(Locale locale) {
return "My Report";
}
public String getDescription(Locale locale) {
return "A description of whatever MyReport generates.";
}
@Override
protected void executeReport(Locale locale) throws MavenReportException {
Sink sink = getSink();
sink.head();
sink.title();
sink.text("My Report");
sink.title_();
sink.head_();
sink.body();
sink.rawText("RAW TEXT!");
sink.body_();
sink.flush();
sink.close();
}
}
Note that half of the API methods are not even called. Also pay extra attention to getOutputName() and how the output directory and file in your target/site/ is built.
As for building the plugin, the dependencies which worked for me after experimenting for hours and reading code (really, why did you have to separate API and implementation? Are there any other implementations?):
<dependency>
<groupId>org.apache.maven.reporting</groupId>
<artifactId>maven-reporting-api</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>org.apache.maven.reporting</groupId>
<artifactId>maven-reporting-impl</artifactId>
<version>2.0.4.3</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>2.0.1</version>
</dependency>
This is how you use it in your POM:
<reporting>
<plugins>
<plugin>
<groupId>my.group</groupId>
<artifactId>myartifact</artifactId>
<version>1.0-SNAPSHOT</version>
<reportSets>
<reportSet>
<reports>
<report>myreport</report>
</reports>
</reportSet>
</reportSets>
</plugin>
</plugins>
</reporting>
