I can use Maven to compile and test a program
mvn compile
mvn test
Is there a lifecycle command to simply run the program, or generate a script which will run the program?
If you are asking this question, it means it's unclear to you what the Maven lifecycle really is.
There is no lifecycle command, only a build lifecycle, which is made up of different phases.
So to make it clear: there is a build lifecycle, which is made up of phases, which are made up of plugin goals.
When you are invoking Maven with
mvn compile
You are invoking a build phase. In Maven, there is a list of predefined ordered phases. When you invoke a phase, all of the phase before it are also invoked. Invoking a phase means that you are invoking all of the plugins that are bound to this phase. For the compile case, this means it will, among others, invoke the maven-compiler-plugin wich is bound to the compile phase by default.
So to answer your question strictly: no, there is no lifecycle command to do that.
However, you can configure a plugin in your POM, which will be bound to a certain phase, and invoke that phase. For that, you can refer to #manouti's answer which introduces the exec-maven-plugin.
There is no lifecycle phase to do this but you can bind the exec-maven-plugin, specifically the exec:java goal to it. For example, to run the goal on the package phase:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>run-java</id>
<phase>package</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>main.Class</mainClass>
</configuration>
</plugin>
Related
We have a use-case where we want to do sonar analysis as part of site generation. That is whenever "mvn install site:site" is invoked, we want sonar:sonar to be invoked as well as part of that.
We tried following plugin configuration, but that doesn't work to execute sonar goal as part of site phase (we tried "pre-site" phase too but that did not work as well):
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.3.0.603</version>
<executions>
<execution>
<id>sonar-site</id>
<phase>site</phase>
<goals>
<goal>sonar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<build>
Just for experimenting, when we changed: <phase>site</phase> to <phase>post-integration-test</phase> in the above snippet, sonar goal started getting executed after IT execution.
Is there something wrong in compatibility between sonar-maven-plugin and maven-site-plugin. Will appreciate any input or alternate approach to resolve this.
You bound the SonarQube Maven plugin to a site phase, but you didn't execute that phase. You passed site:site which means execute a site goal of the maven-site-plugin.
You have to execute: mvn install site
The solution with post-integration-test works, because that stage is executed by install phase (more or less).
Read more about Maven Lifecycle Reference.
When I build a project with Maven, dependencies with scope test seems to be out of scope during the integration-test phase. Is this by design, or is there anything I can do to have dependencies with scope test to be included during the integration-test phase?
One answer here on SO suggests that test dependencies are in scope during the integration-test phase, but the answer is just a statement with no references. However, this does not appear to be how Maven works for me.
When I change a given dependency's scope from test to compile, the given dependency is (as expected) available during the integration-test phase.
Should the test scope apply to the integration-test phase, or will I have to set dependency scope to compile in order for them to be available during the integration-test phase?
This is the relevant part of the POM file. What I'm doing is that I attempt to start an instance of a MockServer during the integration test phase. However, it fails as the com.company.msd dependency not is included.
<dependencies>
<dependency>
<groupId>com.company.msd</groupId>
<artifactId>MockServerDemo</artifactId>
<version>0.0.4</version>
<scope>test</scope>
</dependency>
</dependencies>
[...]
<plugin>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-maven-plugin</artifactId>
<version>3.9.17</version>
<configuration>
<serverPort>1080</serverPort>
<proxyPort>1081</proxyPort>
<logLevel>DEBUG</logLevel
<initializationClass>com.company.msd.server.DefaultExpectationInitializer</initializationClass>
</configuration>
<executions>
<execution>
<id>pre-integration-test</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
Note! If I add the dependency as a plugin dependency, it works. However, I'm still curious if Maven by design not includes test scoped dependencies in the integration-test phase.
According to maven-failsafe-plugin's integration-test mojo documentaion (link) and source code (link) it does require resolution of dependencies in test scope. In other words, it's not the phase that determines which dependency scope is used but the actually employed mojo.
In your case mockserver-maven-plugin's start mojo does indeed only require resolution of dependencies in compile+runtime scope (link), whereas stop mojo requires the default runtime resolution scope (link). See requiresDependencyResolution descriptor in Maven Mojo API documentation (link) for further details.
If you get similar problems in the future, I suggest that you print out effective pom to understand how Maven interprets your configuration, or otherwise run Maven with -X flag so that you can see the actual class path for each mojo. Maven documentation may be ambiguous at times, but this way you can at least be sure how Maven works in practice.
I kind of understand most things in Maven, but trying to understand goals is very frustrating. The main problem is that Maven seems to want to hide everything and anything to do with Goals.
If I have a plugin with an execution, and this execution has a goal,
does the goal attach itself somewhere near particular other goals?
How does it know which phase it belongs in?
Does it somehow replace some other goal?
Case in point :
<plugins>
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<id>wsimport-from-jdk</id>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<executable>${tool.wsimport}</executable>
<wsdlUrls>
<wsdlUrl>http://WorkPC:8080/server-web/AirlineWS?wsdl</wsdlUrl>
</wsdlUrls>
<packageName>com.bluewalrus</packageName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
This is a wsImport goal which generates artifacts from a web service. It happens before I compile my project. How on earth can this XML tell me where this goal should execute? It just doesn't seem clear to me.
I mean what I am saying, is that I would expect something like "bind-to-process-resources right after goal-xyz". It all seems a bit nebulous to me.
Unfortunately, the pom.xml cannot tell you everything about how a plugin's goals are bound. A plugin can define a default lifecycle phase to bind to and this will not be reflected in the pom.xml. Looking at the documentation for the jaxws-maven-plugin I see this line for the wsimport goal:
Binds by default to the lifecycle phase: generate-sources.
You can override the lifecycle phase to bind to by adding a <phase> element to the plugin's <execution>. For example, if you wanted the goal to run right before packing the artifact (not sure why you would, but bear with me for this example) you could specify <phase>package</phase> after the execution <id>
I would recommend taking a look at the official Maven guide to configuring plugins for more details.
Also you would want to read:
The phases's order in standard lifecycles
The phases's bindings for lifecycle and packaging types
I'm looking at the plugin section of a pom I'm inspecting and found this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-docck-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>pre-site</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
If you observe the execution section you will notice that it does not have an id tag. My question is how is the id tag used by Maven and how the absence of one influences the observed behavior. I looked into Maven tutorials and could infer that id's of different execution phases must be unique, in a pom not necessarily across the inherited poms, but it did not mention how it is utilized.
For Maven 3.0.x at least, when not specified, the ID for an execution is default-goalName. So for the example you have, the ID would be default-check. The value default-cli may also be used to configure command line executions.
The execution IDs are used when creating the effective POM from the POM itself, any parent POMs (including the Maven super POM), and settings.xml. Maven merges configuration for plugin executions having the same ID across these POMs. Here's an example. Assume this plugin config is in a parent POM (only Maven super POM is higher up in the hierarchy.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<!-- default-jar is the ID assigned to the jar:jar execution
included automatically by Maven. This demonstrates how we
can tweak the built-in plugin executions to meet our needs.
Note we do not have to specify phase or goals, as those are
inherited. In the example we add a configuration block and
change the values of the <forceCreation> and <finalName>
elements. -->
<execution>
<id>default-jar</id>
<configuration>
<finalName>firstJar</finalName>
<forceCreation>true</forceCreation>
</configuration>
</execution>
<!-- Add an execution of the jar plugin to build a jar with the
same contents but different name. We assign an execution ID.
Because we are not inheriting config for this execution it's our
responsibility to specify phase and goals, as well as the config
we want. Executions are run in order so this one will run after
the default. -->
<execution>
<id>another-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<finalName>duplicateJar</finalName>
</configuration>
</execution>
<!-- Configure plugin behavior if we execute the jar:jar goal
directly from the command line. Don't bind this to a phase;
we don't want to run this as part of the normal lifecycle. -->
<execution>
<id>default-cli</id>
<configuration>
<finalName>cmdLineJar</finalName>
</configuration>
</execution>
</executions>
</plugin>
With the above config:
mvn clean package - builds firstJar.jar and duplicateJar.jar
mvn jar:jar - builds cmdLineJar.jar (note, no clean lifecycle!)
mvn clean jar:jar - removes target dir, builds empty (except for manifest) cmdLineJar.jar; because jar:jar does not run the full lifecycle, just one goal
mvn clean prepare-package jar:jar - runs lifecycle thru prepare-package, then builds a non-empty cmdLineJar.jar
The problem can not be treated with respect to id tag only but notice the different values of it through the examples. This has been tested with maven 3.0.5. Consider the following pom part:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-docck-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>some-other-other-id</id> <!-- No goal for execution is defined -->
<phase>pre-site</phase>
</execution>
<execution>
<phase>pre-site</phase> <!-- No id for execution is defined -->
<goals>
<goal>check</goal>
</goals>
</execution>
<execution>
<id>some-id</id> <!-- No phase for execution is defined -->
<goals>
<goal>check</goal>
</goals>
</execution>
<execution>
<id>some-other-id</id> <!-- Both id and phase defined -->
<phase>pre-site</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
When run mvn clean site from command line it outputs the following:
[INFO] --- maven-docck-plugin:1.0:check (default) # MavenJavaApplication ---
[INFO] Skipping unsupported project: MavenJavaApplication
[INFO] No documentation errors were found.
[INFO]
[INFO] --- maven-docck-plugin:1.0:check (some-other-id) # MavenJavaApplication ---
[INFO] Skipping unsupported project: MavenJavaApplication
[INFO] No documentation errors were found.
Notice that the execution outputs are always in form of:
<plugin-name>:<plugin-version>:<phase> (<execution-id>)
Case 1: No goal for execution is defined
From Build lifecycle basics:
A plugin goal represents a specific task (finer than a build phase) which contributes to the building and managing of a project. It may be bound to zero or more build phases. A goal not bound to any build phase could be executed outside of the build lifecycle by direct invocation. (...) Moreover, if a goal is bound to one or more build phases, that goal will be called in all those phases.
From Guide to configuring plugins: Configuring build plugins:
But if the goal is not bound to any lifecycle phase then it simply won't be executed during the build lifecycle.
From what is quoted, it may be concluded that the execution with id some-other-other-id can be ran from the command line, but that is not so, it can never be ran - it will be covered in the 5th example.
Case 2: No id for execution is defined
The definition of goal and a phase in the first execution is enough for it to get run so it gets assigned a default execution id of value default and it gets executed.
Case 3: No phase for execution is defined
Since the phase is not defined anywhere this execution does not get executed. It can be verified by the fact that the output does not contain the line with its execution id.
Case 4: Both id and phase defined
This execution defines all three: an id, a phase and a goal so it gets executed.
Case 5: CLI execution
If you run (read the syntax in the docck plugin documentation):
mvn docck:check -Doffline=true
it will output:
[INFO] --- maven-docck-plugin:1.0:check (default-cli) # MavenJavaApplication ---
From Guide to configuring default mojo executions:
Starting in Maven 2.2.0, each mojo invoked directly from the command line will have an execution Id of default-cli assigned to it, which will allow the configuration of that execution from the POM by using this default execution Id
You can provide the properties for the goal executed from CLI in three different ways:
in the command line directly
in the plugin configuration
in the execution tag with id of value default-cli
Specifically, the above command is equivalent of running
mvn docck:check
with the pom containing:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-docck-plugin</artifactId>
<version>1.0</version>
<configuration>
<offline>true</offline>
</configuration>
</plugin>
or:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-docck-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>default-cli</id>
<phase>pre-site</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<offline>true</offline>
</configuration>
</execution>
</executions>
</plugin>
This last part comes in handy if you want to keep the global configuration for some common properties in different executions, but you want a complete other set of properties for running from CLI.
Case 6: The default execution
Since the maven-docck-plugin has no default binding I'll cover it with the maven-compiler-plugin. Consider an empty pom with jar packaging. If you run:
mvn clean install
it will trigger the compile phase also and you will see in output:
[INFO] --- maven-compiler-plugin:2.3.1:compile (default-compile) # MavenJavaApplication ---
To cover the value of the id tag, from Guide to Configuring Default Mojo Executions:
Likewise, each mojo bound to the build lifecycle via the default lifecycle mapping for the specified POM packaging will have an execution Id of default-<goalName> assigned to it, to allow configuration of each default mojo execution independently.
If you run mvn help:effective-pom you will find the default execution definition for compiler plugin in output:
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
It gets inherited from super POM for the jar packaging type:
When no packaging is declared, Maven assumes the artifact is the default: jar. The valid types are Plexus role-hints (read more on Plexus for a explanation of roles and role-hints) of the component role org.apache.maven.lifecycle.mapping.LifecycleMapping. The current core packaging values are: pom, jar, maven-plugin, ejb, war, ear, rar, par. These define the default list of goals which execute to each corresponding build lifecycle stage for a particular package structure.
In other words, the above default execution definition is the consequence of a default lifecycle mapping (documentation, definition ) for the compiler-plugin:
The Compiler Plugin has two goals. Both are already bound to their proper phases within the Maven Lifecycle and are therefore, automatically executed during their respective phases.
compiler:compile is bound to the compile phase and is used to compile the main source files.
Uniqueness of an execution id tag
From Guide to configuring plugins.html: Using the executions tag:
Note that while execution id's have to be unique among all executions of a single plugin within a POM, they don't have to be unique across an inheritance hierarchy of POMs. Executions of the same id from different POMs are merged. The same applies to executions that are defined by profiles.
I developed a maven plugin with #aggregator annotation.
If I run
mvn clean compile my:artifact:task package
then it compiles 2 times.
So I insert this fragment into my pom
<plugin>
<groupId>my</groupId>
<artifactId>artifact</artifactId>
<version>1.0.0-SNAPSHOT</version>
<executions>
<execution>
<id>post-classes</id>
<phase>process-classes</phase>
<goals>
<goal>task</goal>
</goals>
</execution>
</executions>
</plugin>
but then it will run on each module (# aggregator is seemingly ignored).
How do I let the plugin run once after compiling?
Edit:
My problem refers to the default lifecycle of eclipse tycho. But there is an major bug so I was very confused.
From this:
For mojos executed directly from the CLI, the mojo will only be executed once and not per each project in the reactor. For mojos bound to a lifecycle phase, the mojo will be executed for each project where the lifecycle binding is present.
You have two options:
If you insist on using the aggregator annotation: remove the lifecycle binding and run it via command line, such as "mvn clean compile my:artifact:task jar:jar". Similar to assembly:assembly which is designed to be invoked directly from the command line, and should never be bound to a build lifecycle phase.
If you insist on binding your plugin to lifecycle, remove the aggregator annotation and follow this article. The idea is to examine the project properties where maven is currently running on.