- A Concurrent Affair - https://www.concurrentaffair.org -

Invoking Maven from Java

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 [1]. Here’s how to use it:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   private void invokeMavenInstall(File [2] 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 [3].singletonList("install"));

        Invoker invoker = new DefaultInvoker();
        invoker.setMavenHome(new File [2](System [4].getenv("M3_HOME")));
        invoker.setOutputHandler(new SystemOutHandler());
        invoker.setErrorHandler(new SystemOutHandler());
        invoker.setLogger(new PrintStreamLogger(System [4].out, InvokerLogger.DEBUG));
        InvocationResult result = invoker.execute(request);
        if (result.getExecutionException() != null) {
            throw result.getExecutionException();
        }
        assertEquals(0, result.getExitCode());
    }
}

The interesting bit here is the request.setShellEnvironmentInherited(false); line. Without it, the MavenCommandLineBuilder.setShellEnvironment method adds an environment variable M2_HOME to it, which prevents Maven from starting up [5].

[6] [7]Share [8]