1

What is the problem when I execute the maven command in the loop ? The goal is to update the version of pom.xml of the list of bundles. The first iteration, maven execute correctly (update pom.xml), but it makes error for all item after.

for (String bundlePath: bundlesToUpdate)
{
    MavenCli cli = new MavenCli();
String[] arguments = {
    "-Dtycho.mode=maven", 
        "org.eclipse.tycho:tycho-versions-plugin:set-version", 
    "-DgenerateBackupPoms=false", 
    "-DnewVersion=" + version};
    int result = cli.doMain(arguments, bundlePath, System.out, System.err);
}

Same error with the code:

`MavenCli cli = new MavenCli();
for (String bundlePath: bundlesToUpdate) 
{
    String[] arguments = {
    "-Dtycho.mode=maven", 
    "org.eclipse.tycho:tycho-versions-plugin:set-version", 
    "-DgenerateBackupPoms=false", 
    "-DnewVersion=" + version};
int result = cli.doMain(arguments, bundlePath, System.out, System.err);
}`

First time, it's ok:

[main] INFO org.eclipse.tycho.versions.manipulation.PomManipulator -   pom.xml//project/version: 2.2.6-SNAPSHOT => 2.2.7-SNAPSHOT
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - ------------------------------------------------------------------------
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - Reactor Summary:
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - 
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - XXXX project   ....................... SUCCESS [  0.216 s]
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - com.sungard.valdi.bus.fixbroker.client.bnp ........ SKIPPED
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - XXX project Feature ...................... SKIPPED
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - ------------------------------------------------------------------------
[main] INFO org.apache.maven.cli.event.ExecutionEventLogger - BUILD SUCCESS

After the errors are:

[main] ERROR org.apache.maven.cli.MavenCli - Error executing Maven.
[main] ERROR org.apache.maven.cli.MavenCli - java.util.NoSuchElementException
  role: org.apache.maven.eventspy.internal.EventSpyDispatcher
roleHint: 
[main] ERROR org.apache.maven.cli.MavenCli - Caused by: null
[main] ERROR org.apache.maven.cli.MavenCli - Error executing Maven.
[main] ERROR org.apache.maven.cli.MavenCli - java.util.NoSuchElementException
      role: org.apache.maven.eventspy.internal.EventSpyDispatcher
roleHint: 
Nhu Phung
  • 79
  • 12

3 Answers3

2

The solution I found is to use Maven Invoker and it works fine for the same functionality:

    public class MavenInvoker {

    public static void main(String[] args) throws IOException, NoHeadException, GitAPIException 
{
    MavenInvoker toto = new MavenInvoker();

    toto.updateVersionMavenInvoker("2.2.8-SNAPSHOT", "TECHNICAL\\WEB" );
}

private InvocationRequest request = new DefaultInvocationRequest();
private DefaultInvoker invoker = new DefaultInvoker();

public InvocationResult updateVersionMavenInvoker(String newVersion, String folderPath)
{
    InvocationResult result = null;
    request.setPomFile( new File(folderPath+"\\pom.xml" ) );

    String version =  "-DnewVersion="+newVersion;
    request.setGoals( Arrays.asList("-Dtycho.mode=maven", 
            "org.eclipse.tycho:tycho-versions-plugin:set-version", 
            "-DgenerateBackupPoms=false", 
            version) );
    try {
        result = invoker.execute( request );
    } catch (MavenInvocationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return result;
}

}

Nhu Phung
  • 79
  • 12
  • The question was about how to use maven embedder. I think it is possible. The solution you provided is using another library. So I dont know if it should be tagged as the answer. I personally have a similar requirement and prefer maven-embedder over invoker, cause the latest involves IO operations to write/read a pom.xml from the system, which is not necessary for my requirement. – Özgün Aug 07 '23 at 08:37
2

This works for me inside a custom maven plugin (using Maven 3.5.0):

ClassRealm classRealm = (ClassRealm) Thread.currentThread().getContextClassLoader();
MavenCli cli = new MavenCli(classRealm.getWorld());
cli.doMain( ... );

The plexus Launcher sets the context class loader to its ClassRealm, which has access to the "global" ClassWorld.

Not sure how stable that solution is, but so far looking good.

Used imports:

import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.apache.maven.cli.MavenCli;
Alexander Klimetschek
  • 3,585
  • 31
  • 36
  • it gives classcast exception – Gaurav Jun 17 '20 at 07:42
  • This was useful, but I discovered the hard way that I had to do: final ClassRealm classRealm = (ClassRealm) Thread.currentThread().getContextClassLoader(); final ClassWorld classWorld = classRealm.getWorld(); classWorld.disposeRealm("maven.ext"); final MavenCli cli = new MavenCli(classWorld); – Infernoz Dec 07 '20 at 13:09
  • It's such a pity that the official documentation is so damned minimal as to be near useless, including the Javadocs(!), as is sadly a lot of Apache, with Maven seemly one of the worst parts, but at least I can look at the Maven plugins source code on Github... – Infernoz Dec 07 '20 at 13:16
  • I've come to the bitter conclusion that MavenCli isn't usable in a plugin, the logs get messed up, so IDEA thinks it has prematurely stopped! I had a look at the Apache Maven Invoker library, used by the Maven Invoker plugin, and it builds a CLI string for the Maven EXE and runs that! This is obvious lack of confidence in their own libraries!!! – Infernoz Dec 09 '20 at 04:18
  • I feel you. I was assuming the solution might not be stable long term. Unfortunately I don't know more, haven't used that code again with newer Maven versions. – Alexander Klimetschek Dec 09 '20 at 04:59
0

See the email thread for a more detail explanation: https://dev.eclipse.org/mhonarc/lists/sisu-users/msg00063.html

It seems the correct way is to give MainCli a ClassWorld instance on construction so it can maintain a proper state through multiple calls.

Example:

final ClassWorld classWorld = new ClassWorld("plexus.core", getClass().getClassLoader());
MavenCli cli = new MavenCli(classWorld);
String[] arguments = {
    "-Dtycho.mode=maven", 
        "org.eclipse.tycho:tycho-versions-plugin:set-version", 
    "-DgenerateBackupPoms=false", 
    "-DnewVersion=" + version};
int result = cli.doMain(arguments, bundlePath, System.out, System.err);
rveach
  • 2,081
  • 15
  • 25