How call a maven plugin explicitly and non running otherwise? - java

Eventually I generate some Java code with explicite mvn generate-sources which calls CXF plugin defined in pom.xml.
Q: How to configure plugin to make it running when I call it explicitly and not running otherwise?
If I set phase to generate-sources, then mvn generate-sources works, but mvn compile also triggers it (that's unwanted).
If I set phase to none, then mvn generate-sources does nothing (unwanted), but mvn compile does not trigger it (ok).
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<!--<phase>none</phase>-->

You can run any plugin from command line and as such exclusively it (and not part of a Maven phase, in this case), simply configuring the plugin in your POM (plugins section) with a generic configuration (not nested within any execution sub-section).
As such, the given configuration will be used for any execution. Since the concerned plugin does not have any default binding through any Maven packaging (which instead happens for other plugins, i.e. Maven Compiler or Surefire plugins), then the configuration will be picked up only by your command line execution.
mvn org.apache.cxf:cxf-codegen-plugin:wsdl2java
Would then run the plugin you configured with the required configuration, given in your POM:
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<configuration><!-- HERE YOUR CONFIG --></configuration>
</plugin>
As you can see, there is no execution (and hence no phase) described for the plugin, but a global configuration is supplied. As global, it will be used by your command line execution as well.
This approach is slightly different than what you tried:
mvn generate-sources
When executing generate-sources, you are executing a phase and as such any other preceding phase. However, the preceding phases do not affect your project and as such you would get the same behavior, plus the side effect of also having it as part of the compile phase.
If you really want to have it as part of the generate-sources phase (for whatever reason) and keep on running mvn generate-sources without the side effect described above, then you can wrap it in a profile, adding to your POM:
<profiles>
<profile>
<id>generate-cxf</id>
<build>
<defaultGoal>generate-sources</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions><!-- HERE YOUR EXECUTIONS--></executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
You could then execute:
mvn generate-sources -Pgenerate-cxf
And it will activate the profile above and as such your plugin and executions but not impacting (side effects) any other phase or the default build.
Moreover, via the defaultGoal element configuration, you can even simply invoke:
mvn -Pgenerate-cxf
And you will have exactly the same behavior (although a bit cryptic I would say).
Last but not least, since Maven 3.3.1, you can invoke just a simple plugin execution (keeping your binding to the none phase this time) from command line (specifying the desired execution id) as following:
mvn org.apache.cxf:cxf-codegen-plugin:VERSION_HERE:wsdl2java:#EXEC_ID_HERE
The command above will only (and only) execute your target execution.

Related

'mvn clean' vs.'mvn clean install' (when a plugin execution is attached to 'clean')

Let's say I want to install project-local dependencies (jar files) to my local maven repository (~/.m2) prior to compiling the project so I can reference them in my POM just like I would reference any dependency from Maven Central. Currently, I'm using Maven install plugin's install-file goal attached to the 'clean' phase (because my IDE uses it), like so:
<dependencies>
<dependency>
<groupId>group.id</groupId>
<artifactId>artifact.id</artifactId>
<version>artifact.version</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<executions>
<execution>
<id>install-my-local-dependency</id>
<phase>clean</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>group.id</groupId>
<artifactId>artifact.id</artifactId>
<version>artifact.version</version>
<file>${project.basedir}/lib/local-dep.jar</file>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
When I execute mvn clean (or its equivalent in the IDE), everything runs as I'd expect:
--- maven-clean-plugin:2.5:clean (default-clean) # MyProject ---
--- maven-install-plugin:2.5.2:install-file (install-...) # MyProject ---
Installing ${project.basedir}/lib/local-dep.jar to ~/.m2/repository/group.id/artifact.id/local-dep.jar
But when I execute mvn clean install instead (or its equivalent in the IDE), I get the following error:
Failed to execute goal on project MyProject: Could not resolve dependencies for project com.example.MyProject:jar:1.0: Could not find artifact group.id:artifact.id:jar:artifact.version in central (https://repo.maven.apache.org/maven2) -> [Help 1]
For some reason, Maven install plugin's install-file goal either does not run in this case, or doesn't run soon enough. Why? The other StackOverflow answers I found explain differences between both commands but in my eyes, they do not explain this particular difference as my project has no modules.
Is there a better way of doing the same thing cross-platform, even on build servers (e.g. Jenkins) and with at least one other dependent project?
Should it be any help, I have the following Maven versions:
CLI: 3.6.0
IDE: 3.3.9
Maven first analyses the pom.xml and then calls the goals/phases. The analysis itself is complicated and has different depths, so I guess that calling clean alone will not make Maven analyse the dependencies, but calling clean install does so. Note that the analysis of the POM only happens once, not again for every goal/phase.
Generally, your approach cannot be recommended. Usually, you put project dependencies into remote Maven repositories, so that they can be resolved through them. If you work inside a company, you should set up a Nexus/Artifactory server that handles your artifacts.
If you want people outside your company to build the artifact, you need to find a provider for Maven repositories. I guess that github/gitlab can help you here. Then you need to add those repositories to the POM.

How to force maven to run build-lifecycle before site-lifecycle?

After spending several hours trying to find out whats the problem I come to the conclusion that I need to know:
How can I force maven to execute the lifecycle phases clean, build and site in exact this order: clean -> build -> site?
Problem / scenario:
I have to multimodule projects with identical moduls:
pSuccess
|-pSuccessClient
|-pSuccessEJB (has pSuccessClient as dependency)
|-pSuccessEAR (has pSuccessEJB as dependency)
and
pFail
|-pFailClient
|-pFailEJB (has pFailClient as dependency)
|-pFailEAR (has pFailEJB as dependency)
Both projects have distribution repositories for snapshots and releases in our central nexus artefact repository but none of them has been deployed to it, meaning the nexus is empty.
When I run mvn clean package site on the pSuccess-project the target directory is deleted (clean-lifecycle), then the modules are all build (build-lifecycle) and finally the reports are generated (site-lifecycle) correctly on the freshly build modules - BUILD SUCCESS! While "debugging" the process I figured out that during the build-lifecycle the needed clientDependency is placed in the lokal maven repository and then used for the EJB, same with the EJB for the EAR module. Working smoothly as expected.
But when I do the same on the pFail-project maven executes the site-lifecycle after the clean-lifecycle and before the build-lifecycle. As you can expect this results in a failed build as maven can't find the needed dependency (Client) for the EJB. This is quite locically as it hasn't been build yet. I can enforce this result every time I run the command. There's not phase of the build-lifecycle be run - no compilation, just nothing. Maven tries to execute the site-lifecycle first. The build is only successfull when I run a mvn clean deploy and then another mvn clean package site, becuase then the artefact is read from the nexus. But again site-lifecycle is executed before build-lifecycle. Note Building the project only via mvn clean package works fine without any problems. All modules are build in the correct order. But when I add the site lifecycle it fails.
I read the maven documentation about lifecycle but I can't figure out why site is run before build. In some questions here on SO I read that plugins, which shall be executed in the same phase, are executed in the order they are listed in the pom.xml. So I checked that too, but the <build> tag is definied before the <reporting> tag.
So why is maven executing the site-lifecycle before the build-lifecycle in one of my project and how can I force maven to execute the lifecycles in the right order: clean -> build -> site ?
P.S: I run all maven commands on command line in windows 7.
edit
I know about the lifecycles and phases, meaning I know what's the differenze between package, install, deploy is - that is not part of the question!
For those who do not believe about the execution order: This is the output when I run mvn clean install site, showing that site-lifecycle is executed before build-lifecycle. It doesn't matter if I run mvn clean package site or mvn clean install site. Again, running single mvn clean package(or install) works fine, but not when I want to generate site too. Then site is executed first.
After digging several more hours I found a solution for my problem:
Both projects use the maven-javadoc-plugin during for reporting
<reporting>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven.javadoc.version}</version>
<!-- DocLint je nach Profil ausschalten (siehe oben) -->
<configuration>
<additionalparam>${javadoc.opts}</additionalparam>
</configuration>
</plugin>
...
</reporting>
In the EJB of the failing project we also use the build-helper-maven-plugin in the generate-sources phase of the build lifecycle.
<build>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
....
</plugin>
...
</build>
It seems that both plugins collide during the generate-sources phase.
After chaning the maven-javadoc-plugin to use the following ReportSet the site generation works fine
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven.javadoc.version}</version>
<!-- Disable DocLint correspondening to java version -->
<configuration>
<additionalparam>${javadoc.opts}</additionalparam>
</configuration>
<reportSets>
<reportSet>
<reports>
<report>javadoc-no-fork</report>
<report>test-javadoc-no-fork</report>
</reports>
</reportSet>
</reportSets>
</plugin>
I still don't really understand why it collades but at least my project is working.

How to remote debug tests when mvn release:perform [duplicate]

During the maven release:perform goal, the prepared tag is being checked out from SCM and a build seems to be attempted in a forked maven instance.
I'd like the tests to be skipped at that point, because for whatever reason, they fail (the build involves running a test web-application via cargo, and I believe this just doesn't work well in this environment).
Is there any way to instruct maven to do this?
You can specify arguments to the forked maven instance on the command line:
mvn release:prepare -Darguments="-DskipTests"
mvn release:perform -Darguments="-DskipTests"
or specify a maven-release-plugin configuration in your pom, perhaps under pluginManagement:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<arguments>-DskipTests</arguments>
</configuration>
</plugin>

Maven: lifecycle phase to run a program?

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>

Maven class post-processing

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.

Categories