Hullo!
Upgrading to Maven 3
Thursday, 26July2012 (#)
Are there major issues anyone is having with upgrading to Maven 3.x from Maven 2.x? If there are still any blockers I'd like to fix them.
As someone who’s put some effort into upgrading to Maven 3 at work, I thought I’d mention one blocker.
Maven 1 to Maven 2 was a complete rewrite for builds — your
project.xml became a
pom.xml, for a clear separation.
Maven 3 is largely an extension of the 2.x series and intended to
be compatible. As a user, the compatibility is good, but the internals
break a few things for plugin writers. And, like any users of Maven
at scale, we have custom plugins.
mojo-executor was the problem.
It’s a library to invoke Maven goals from within a mojo,
so your build plugin can call out to other plugins for its implementation.
Under Maven 2 the code to invoke Maven recursively used a
PluginManager. However in Maven 3, although you can get access
to an instance of PluginManager,
it’s not going to help you:
public void executeMojo( MavenProject project, MojoExecution execution, MavenSession session )
throws MojoExecutionException, ArtifactResolutionException, MojoFailureException, ArtifactNotFoundException,
InvalidDependencyVersionException, PluginManagerException, PluginConfigurationException
{
throw new UnsupportedOperationException();
}
Under Maven 3 we need to get a BuildPluginManager instead. So,
we need two paths in the code: one that tries to get a BuildPluginManager
and a fallback that uses the PluginManager if that’s all we can
get. So what happens when we load a mojo that uses the new
class BuildPluginManager into Maven 2? It doesn’t know about it:
we get a NoClassDefFoundError. Anyone who’s written Java code to
deal with potentially missing APIs knows the next step: avoid static
use of that class. Rather than defining a field and asking Maven
to inject an instance, try to
get hold of an instance at runtime with a
lookup:
/**
* The Maven PluginManager component.
*
* @component
* @required
*/
private PluginManager pluginManager;
public void execute() throws MojoExecutionException {
ExecutionEnvironment env;
try {
Object o = mavenSession.lookup("org.apache.maven.plugin.BuildPluginManager");
env = executionEnvironment(mavenProject, mavenSession, (BuildPluginManager) o);
} catch (ComponentLookupException e) {
env = executionEnvironment(mavenProject, mavenSession, pluginManager);
}
...
So, if we can look up the Maven 3 version, use it. Otherwise, fall back on the Maven 2 version that was injected. This gives us a plugin that works with old and new Mavens, which is essential during a gradual migration.
That, along with any number of other tweaks, has worked well. My day-to-day
Maven is mvn3 for most projects and I’m enjoying parallel builds,
much better pom validation and a few years of bug fixes. It’s hugely
frustrating to work around bugs that are already fixed by sticking
with obsolete software. I don’t recommend it.
<img src> SVG bugs
Monday, 20February2012 (#)
With constant development and releases it’s easy to forget what the bad old days of working around unfixed browser bugs were like. A great way to remind yourself is to use new features - in this case, SVG.
For compatibility with older browsers, even those with SVG support, it’s sometimes worth embedding images using <object> (as in this roundup of how to get consistent browser behaviour). But, with the current round of modern browsers, an <img> tag should work fine.
SVG’s process for determining the size an image should be rendered at is fairly involved. I should be able to leave the size in the SVG file unspecified and then specify width and height in my img tag:
Firefox is fine with that, but Safari on iOS (Mobile Safari?) gets confused — the result is distorted inconsistently:

So, let’s include a size in the underlying SVG. This won’t affect the display size, because we’re setting that in the HTML, but it works around that bug:
Problem solved!
Using <object> is a great way to get backwards compatibility. Make the SVG an object and embed an img tag pointing at a fallback bitmap:
PNG:
SVG, with PNG fallback:
WebKit shows the image using the size of the underlying SVG rather than the <object> size, so you need a specific file for each size you’re using the image at. Chromium will also sometimes give you scrollbars even when the SVG and object sizes match, but hopefully that’ll be fixed somewhere in Chrome’s ruthless upgrade schedule.
Turning data into graphs
Sunday, 19February2012 (#)
I liked the results from comparing perl and module releases being tested over time. Most of the hoops to jump through were with release dates and getting R to render how I wanted. Here are those hoops, along with how I jumped.
Gathering data
CPAN Testers has a results page for each module. On there, a nice friendly JSON button links to all the test results:
[
{
"status" : "PASS",
"osvers" : "2.11",
"state" : "pass",
"osname" : "solaris",
"platform" : "i86pc-solaris-thread-multi",
"version" : "0.615",
"distribution" : "XML-Writer",
"perl" : "5.10.0",
"fulldate" : "201201182135",
...
},
...
]
This is really easy to parse with JSON.pm.
Release dates
Once we have clones of the Perl git repository and XML::Writer we can get the times at which those releases were tagged. Perl’s tags have used a number of conventions so, in essence:
while read p; do
...
elif git rev-parse --quiet --verify perl-"$p" >/dev/null; then
t="perl-$p"
else
t="v$p"
...
echo "$p,$t","`git show "$t" --pretty=format:Stamp,%ct | grep ^Stamp, | cut -f2 -d,`"
to get output like:
| ID | Tag | Stamp |
|---|---|---|
| XML-Writer-0.3 | xml-writer-0.3 | 944761768 |
| XML-Writer-0.4 | xml-writer-0.4 | 954899991 |
| ... | ||
| 5.5.3 | perl-5.005_03 | 922659709 |
| 5.6.0 | perl-5.6.0 | 953789951 |
| ... |
To CSV
We then process all this using a perl script to get CSV output with the corresponding release dates of the software used in each test.
Generating graphs
Get the data in with d <- read.csv('data.csv') and then start to plot.
A simple plot(x$key, x$value) is a great start when analysing data.
If we want control over how the results look, R is happy to give us
that control. Too much? Maybe!
Dates on the axes
First, plot without labels (plot(d$xmlwriter, d$perl, ..., xaxt='n', yaxt='n')), then add in
axes for dates:
dates <- ISOdate(1999:2012, 1, 1) axis(1, at=dates, labels=format(dates, "%Y")) dates <- ISOdate(seq(2000, 2012, 2), 1, 1) axis(2, at=dates, labels=format(dates, "%Y"))
Highlight certain releases
Use abline to show guidelines for specific releases:
# Perl releases:
abline(h=1305397133, col='darkgray')
abline(h=1271077269, col='darkgray')
abline(h=1198315389, col='darkgray')
abline(h=1027029998, col='darkgray')
abline(h=953789951, col='darkgray')
axis(4, at=c(1305397133, 1271077269, 1198315389, 1027029998, 953789951), c('v5.14.0', 'v5.12.0', 'v5.10.0', 'v5.8.0', 'v5.6.0'), tick=FALSE, las=2)
Trends
For each XML::Writer release, I wanted to show the mean release date of
the perls it had been tested with. We can use aggregate across the tests
to group the perl release dates (d$perl) by the corresponding XML::Writer
version, then summarise by taking the mean and plot it as a line:
points(aggregate(d$perl, list(d$xmlwriter), mean), type='l', col='blue')
This shows that the test perls are getting more recent; it’s nice to to show and to quantify this kind of thing.

![[Feed]](feed.png)