I want to make my Maven build fail when I forget to declare serialVersionUIDs in a Serializable class. With javac, that’s easy:
$ javac -Xlint:serial -Werror Source.java
Directly translating that to Maven doesn’t work:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<compilerArgument>-Xlint:serial -Werror</compilerArgument>
</configuration>
</plugin>
The compilerArgument is quoted, so javac receives only one argument, containing -Xlint:serial -Werror, instead of -Xlint:serial and -Werror as separate arguments. So you read the docs, and find compilerArguments:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<compilerArguments>
<Xlint:serial />
<Werror />
</compilerArguments>
</configuration>
</plugin>
This looks weird – the colon makes serial element in the Xlint namespace, which isn’t declared anywhere – but it works… until you want to do a release:
$ mvn release:prepare
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-release-plugin:2.3.2:prepare (default-cli) on project my-project: Error reading POM: Error on line 58: The prefix "Xlint" for element "Xlint:serial" is not bound.
Apparently, the regular POM reader handles XML namespaces in another way than the one used by the release plugin.
So how do I pass javac multiple command-line switches when some of those switches contain characters which aren’t valid for plain XML elements, without breaking the release plugin?
It seems that while spaces are escaped in
compilerArgument, the same isn’t true for quotes. So, if you surround the spaces in the argument with quotes, you get two arguments:This invokes
javac "-Xlint:serial" "-Werror"rather thanjavac "-Xlint:serial -Werror".There’s nothing in the docs about this that I can find.