Kevin Workman
Kevin Workman

Reputation: 42174

How does exec.mainClass work without exec-maven-plugin?

I have a project that uses the MojoHaus Exec Maven plugin to run some Java code. Here's the pom.xml file:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>io.happycoding</groupId>
  <artifactId>google-cloud-vision-hello-world-standalone</artifactId>
  <version>1</version>

  <properties>
    <mainClass>io.happycoding.vision.CloudVisionHelloWorld</mainClass>
    <exec.cleanupDaemonThreads>false</exec.cleanupDaemonThreads>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-vision</artifactId>
      <version>1.100.0</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <mainClass>${mainClass}</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

This works fine, and I can run my code using this command:

mvn clean package exec:java

I understand that the exec-maven-plugin plugin, which is specified in the plugins tag, runs the code using the mainClass property.

I was surprised to find that this pom.xml also works:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>io.happycoding</groupId>
  <artifactId>google-cloud-vision-hello-world-standalone</artifactId>
  <version>1</version>

  <properties>
    <exec.mainClass>io.happycoding.vision.CloudVisionHelloWorld</exec.mainClass>
    <exec.cleanupDaemonThreads>false</exec.cleanupDaemonThreads>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>google-cloud-vision</artifactId>
      <version>1.100.0</version>
    </dependency>
  </dependencies>
</project>

This file specifies the exec.mainClass property, but does not specify any plugins. However, I can still run my code just fine with this same command:

mvn clean package exec:java

But I don't understand how Maven knows to run this command without any plugins specified.

Is the Exec Maven plugin somehow automatically installed in Maven by default? Or is exec.mainClass somehow setting a property used by a different default tool within Maven?

I tried reading the official documentation, but I didn't see anything that mentions whether the plugin is included by default.

I've found that I can also pass the exec.mainClass property in as a command line argument, but I still don't understand how Maven knows what to do with that without the plugin being explicitly defined.

I much prefer the shorter file, but I want to make sure I understand how it's working and that I'm not missing anything that's going to bite me later.

Upvotes: 0

Views: 847

Answers (1)

When you specify exec:java, you are specifying a plugin, specifically exec-maven-plugin (along with the goal java). Other common plugins that are used by being explicitly identified on the command line rather than being attached to phases such as clean or package include versions, dependency, and archetype (this last of which doesn't even require a POM to be present, since it generally creates new ones).

Note that in your POM you don't attach exec to any phases (that plugin usually isn't); therefore your plugin entry serves only to provide configuration settings in the case you run the plugin explicitly from the command line, in your specific case equivalent to the exec.mainClass property.

Upvotes: 1

Related Questions