Search code examples
javamavenjavacmaven-release-pluginmaven-compiler-plugin

How do I pass javac multiple command-line arguments, some of which include colon, without breaking Maven release plugin?


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?


Solution

  • 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:

    <compilerArgument>-Xlint:serial" "-Werror</compilerArgument>
    

    This invokes javac "-Xlint:serial" "-Werror" rather than javac "-Xlint:serial -Werror".

    There's nothing in the docs about this that I can find.