Make maven run one task before another when running a single plugin - maven

I've got a project set up using the Maven Cargo plugin to launch Tomcat with my webapp deployed in it, along with some other webapps that are needed for support. This works great. Unfortunately, when I run "mvn cargo:run" it doesn't do a build first, but instead just actually starts Tomcat running the code the last time I did do a build.
Previously I used the tomcat7 plugin instead, and that did do a build first and always ran the current version of the source code. As such, I could change my code and run "mvn tomcat7:run" and know that the code changes had been built and were running.
I can't find any way with the Cargo plugin to make it do this, but is there some way with Maven to make it at least run the Package phase when I run a specific plugin so that it will build the WAR file correctly first?

The Tomcat plugin automatically invokes the compile phase prior to executing itself. The Cargo plugin won't do that. In order to compile your code before executing the plugin, you need to run
mvn clean compile cargo:run
If you want to start and stop the container automatically before and after your integration tests, you can also bind cargo:start and cargo:stop to Maven's lifecycle phases. See Automatically executing and stopping the container when running mvn install for details.

Here is a full example how to integrate the start via Cargo in the usual build. https://github.com/khmarbaise/maui/tree/master/src/main/resources/it-example-container. You can start the integration tests via mvn -Prun-its clean verify which might be better

A completely different approach would be to use the exec-maven-plugin to execute multiple goals with one command:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<executable>mvn</executable>
<arguments>
<argument>clean</argument>
<argument>compile</argument>
<argument>cargo:run</argument>
</arguments>
</configuration>
</plugin>
<!-- more plugins... -->
</plugins>
</build>
This way, you would only have to call
mvn exec:exec
to clean, compile and run your application.

Related

Maven release plugin executes tests twice

When release:clean release:prepare release:perform is executed , the tests are executed twice
Once at release:prepare , stage run-preparation-goals , task clean verify
And another time on release:perform ,stage run-perform-goals , task deploy
Is there any configuration option to make tests run only on first one and not being executed on perform?
BR
Yulian Oifa
That's because 2 full builds are run as part of the commands you issue.
The release:prepare section performs lots of checks on the code & repository, and does a full build to ensure all tests pass.
The release:perform section tags the repo, then pulls that tag. It performs a build based on that tag and the releases that build to your artefact store of choice (Nexus/Artifactory/wherever).
These steps are designed this way to ensure you don't pollute your repo with a tag on code that doesn't build, and tests are an integral part of your build. Once maven is happy your code is good to go, it creates the tag, and pulls it so it knows for sure that the code being released is the code referenced by the tag, and nothing else. Building that tag for release requires a full build, including the tests.
You can skip the tests on one or other of the steps, or on both, but you're missing the point of tests, and of the release plugin, if you do that.
You can override the goals parameter and add -DskipTests=true.
This parameter will skip the tests only on the perform part.
Eventually i had to change a logic.
I have executed mvn clean install release:clean release:prepare release:perform -Pmaven-release
and create a maven-release. As result the tests are executed only at install
BR
Yulian Oifa
<profile>
<id>maven-release</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<arguments>-Dmaven.test.skip</arguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
You can skip running the tests (managed by surefire plugin) with an explicitly specified parameter -DskipTests:
Something like this:
mvn release:perform -DskipTests
For intergration tests (managed by failsafe plugin) you can use a similar flag: -DskipITs
If you don't want even compile the tests you can use -Dmaven.test.skip=true (for both unit and integration tests)

mvn clean tomcat:run command

When I run "mvn clean tomcat:run" (without specifying any tomcat version) command from command prompt for running my web application, it download tomcat 6.0.29 version dependency as shown below:
org/apache/tomcat/juli/6.0.29/juli-6.0.29.pom
org/apache/tomcat/annotations-api/6.0.29/annotations-api-6.0.29.pom
org/apache/tomcat/catalina-ha/6.0.29/catalina-ha-6.0.29.pom
org/apache/tomcat/coyote/6.0.29/coyote-6.0.29.pom
org/apache/tomcat/tribes/6.0.29/tribes-6.0.29.pom
org/apache/tomcat/jasper-el/6.0.29/jasper-el-6.0.29.pom
org/apache/tomcat/dbcp/6.0.29/dbcp-6.0.29.pom
pom.xml file of the application does not contain any tomcat version it require to run
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
<finalName>esa</finalName>
</build>
So my query is how does it decide to download particular this tomcat version dependency.
Probably the default settings of the tomcat plugin you run.
Try running mvn tomcat:help -Ddetails to see what version of the plugin you use, and how it can be configured.
I think it is an earlier version of the plugin, and you can now use explicit versions, such as
mvn org.apache.tomcat.maven:tomcat6-maven-plugin:2.0:run
mvn org.apache.tomcat.maven:tomcat7-maven-plugin:2.0:run
(or the shorter form)
Seems, you are running the tomcat-maven-plugin from codehaus, whihc has tomcat 6.0.29 built-in. (Seems there was no activity since 2010.)
You should try the tomcat7 plugin from apache.
Regards
Tibor
In command line for maven use --debug option to get explanation of build process. For our case output looks like:
...[DEBUG] Resolving plugin prefix tomcat from [org.apache.maven.plugins, org.codehaus.mojo]
...
[DEBUG] Resolved plugin version for org.codehaus.mojo:tomcat-maven-plugin to 1.1 from repository central (http://repo.maven.apache.org/maven2, releases)...
Actually to explain why we've got tomcat v1.1 without specifying anything about tomcat, remember that maven build process has been customized with build plugins. And each build plugins has own build plugins. So it is enough to examine effective pom file to get clear understanding that almost empty initial pom.xml has quite big effective pom.xml.
To overcome issue just use explicit version of the tomcat plugin.

How to defer Maven test goal after deployment?

I'm using the JBoss and WildFly Maven plugin to deploy my applications.
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>1.0.0.Beta1</version>
</plugin>
</plugins>
The problem that I have found is that if I have some Junit test in my project they are executed before application deployment, leading to a test with an inconsistent application state. Is it possible to configure somehow this plugin to kick-in before the test phase ?
Thanks
This plugin by default executes alongside the package phase and you'll probably have issues attempting to run the plugin before your application is packaged. As an alternative, you could override the maven-surefire-plugin to run your tests in a later phase, such as integration-test, which would be executed after your application has been packaged.
A practical example can be found on this Maven tutorial where it's show how to include failsafe plugin and bind it to the executions of the integration-test and verify phase. This way tests which are engineered as integration test (e.g ending in *IT) will execute only during the integration-test phase.

How to build EAR subproject and deploy it with Jenkins?

My Maven project has a bunch of subprojects like this:
proj/
projEAR/
projCommon/
How can I compile and build the EAR project + deploy it to my web server at the same time?
The way I do it now is:
proj$ mvn clean install
[... builds everything ... ]
proj$ cd projEAR
projEAR$ mvn weblogic:deploy
[... deploys the EAR file ... ]
I'd like to do this with one command. Something like
proj$ mvn clean install projEAR/pom.xml weblogic:deploy
This fails of course, but I hope you get the idea...
Update:
The reason for all this is that jenkins only accepts one pom-file and command. So the problem is really how to configure Jenkins to run Maven twice.
How about the weblogic-deployer-plugin of Jenkins. It will deploy your ear file to a weblogic instance. See WebLogic Deployer Plugin.
Quick and easy workaround
As a workaround, I can advise you to use some Jenkin's Plugins, like "M2 Extra Steps". It allow you to perform extra actions pre or post one. They are often use after a build to perform stuff like generating doc, or deploying something.
I know this is working well ... because I often use this trick :)
Suggestion, never tried
At this moment, I don't have a straight answer. I don't really know how to do it in only one maven command. What I would try is to attach weblogic deploy phase to install.
ear submodule --> pom.xml
<build>
[...]
<plugins>
[...]
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>weblogic-maven-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<configuration>
[...]
</configuration>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
</plugin>
[...]
<plugins>
[...]
<build>
It should work, but once again, I never tried it.
Don't hesitate to give feed back
I couldn't get it to work with Maven. But the way I solved it (in Jenkins) was
Create a pre-build step in Jenkins with the command mvn clean install using the parent pom: proj/pom.xml
Configure the main build as weblogic:deploy using projEAR/pom.xml.
This results in two commands being run: First mvn clean install followed by mvn weblogic:deploy.

Separate Jenkins-Project for deploying to JBoss

I have a Jenkins build which builds a maven project with -PmyProfile clean package. This works fine. Now I want the project be deployable but in a separate task (JBoss deployment) so it can be triggered explicitly via the jenkins GUI. For that, I have the following in my pom:
<profiles>
<profile>
<id>myProfile</id>
<properties>...</properties>
<build>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.0.0.Final</version>
<configuration>
<hostname>localhost</hostname>
<port>29999</port>
<username>admin</username>
<password>admin</password>
<filename>${project.build.finalName}.war</filename>
<name>my-webapp</name>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Now I only want to call that single deployment via mvn jboss-as:deploy separately. But how would I do that? If I create a second Jenkins project, everything needs to be built again, so that's pretty stupid. Building as a separate module does not work, either (some error with "building single modules not supported for maven 3").
Any ideas?
Thanks
It sucks a little, but you can always get stuff from another Jenkins workspace by using filesystem relative path like ../../SecondJob/workspace (or use symlink). I used to do this for the same case (deploying as separate job) for all my projects and it works, it's just not elegant, but I believe there's no built-in solution in Jenkins for that.
Alternatively, it seems there's Jenkins plugin for that, but I haven't used it and can't tell anything about it.
Possible trick:
Have only one project, but parameterize it with DEPLOY parameter set to FALSE by default. The build will contain your main build as well as an Invoke top-level Maven targets post-build step for deployment. The deployment step will be invoked only if DEPLOY is TRUE. To do that you use Conditional Build Step plugin.
There is a new deploy-only goal added in version 7.5.Final. You can grab the war from the first job with Copy Artifact Plugin.
References:
https://docs.jboss.org/jbossas/7/plugins/maven/latest/deploy-only-mojo.html
https://github.com/jbossas/jboss-as-maven-plugin/pull/56/commits

Resources