On one of my work projects right now, I’m adding unit tests to a code generator. The easiest way to make sure the generated code works is to run mvn clean install. Of course, I want to do that from within the unit test and fail the test if the Maven run fails.
Fortunately, there’s Maven Invoker. Here’s how to use it:
[cc_java]
private void invokeMavenInstall(File file) throws MavenInvocationException, CommandLineException {
InvocationRequest request = new DefaultInvocationRequest();
request.setPomFile(file);
request.setBatchMode(true);
request.setDebug(true);
// this prevents M2_HOME from being added in MavenCommandLineBuilder.setShellEnvironment, which then fails to
// start mvn with “Error: Could not find or load main class org.codehaus.plexus.classworlds.launcher.Launcher”
request.setShellEnvironmentInherited(false);
request.setGoals(Collections.singletonList(“install”));
Invoker invoker = new DefaultInvoker();
invoker.setMavenHome(new File(System.getenv(“M3_HOME”)));
invoker.setOutputHandler(new SystemOutHandler());
invoker.setErrorHandler(new SystemOutHandler());
invoker.setLogger(new PrintStreamLogger(System.out, InvokerLogger.DEBUG));
InvocationResult result = invoker.execute(request);
if (result.getExecutionException() != null) {
throw result.getExecutionException();
}
assertEquals(0, result.getExitCode());
}
}
[/cc_java]
The interesting bit here is the [cc_java inline=”true”]request.setShellEnvironmentInherited(false);[/cc_java] line. Without it, the [cc_java inline=”true”]MavenCommandLineBuilder.setShellEnvironment[/cc_java] method adds an environment variable M2_HOME to it, which prevents Maven from starting up.