How to 'mvn jetty:run' from a parent pom? - maven

I have a multi-module project that includes several .war packages. I would like to be able to 'mvn jetty:run' on the parent pom and have each of the sub-modules's .wars deployed on the same embedded jetty instance.
I am able to successfully run 'mvn jetty:run' from each of the the sub-modules, but when I run it on the parent pom it fails and skips the sub-modules.
Trying to run 'mvn jetty:run' from the parent pom results in the following:
[ERROR] Failed to execute goal
org.mortbay.jetty:maven-jetty-plugin:6.1.16:run default-cli) on
project FlashCards_App: Webapp source directory C:\dev\sour
ce_code\FlashCards_App\src\main\webapp does not exist -> [Help 1]
It's true there is no webapp directory on the parent pom.
Here's an excerpt from my pom. The full file can be found here.
<modules>
<module>FlashCards_Domain</module>
<module>FlashCards_GWT</module>
<module>FlashCards_Service</module>
<module>FlashCards_Service_SpringData</module>
<module>FlashCards_Service_Jpa</module>
<module>FlashCards_WebServices</module>
<module>FlashCards_Struts</module>
<module>FlashCards_Test</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>${jetty.version}</version>
</plugin>
</plugins>
</build>
This is basically the same question asked in 2009 in this post. It's been a few years and I'm wondering if there are any other options available now. The previous post proposes two solutions (1) using cargo plugin and (2) building sister wars from a sub-module.

Your best shot is probably to configure the jetty plugin to run multiple webapps. I'm not sure if it would work from your parent pom though, so you might have to use on of your modules as the "launcher" webapp, or create a "dummy webapp" in your parent project.

<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.2.6.v20141205</version>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<webApp>
<contextPath>/</contextPath>
</webApp>
<contextHandlers>
<contextHandler implementation="org.eclipse.jetty.maven.plugin.JettyWebAppContext">
<war>${project.basedir}/app1/target/app1.war</war>
<contextPath>/app1</contextPath>
</contextHandler>
<contextHandler implementation="org.eclipse.jetty.maven.plugin.JettyWebAppContext">
<war>${project.basedir}/app2/target/app2.war</war>
<contextPath>/app2</contextPath>
</contextHandler>
</contextHandlers>
<stopPort>9999</stopPort>
<stopKey>STOP</stopKey>
</configuration>
</plugin>

cd parent_module
mvn jetty:run -pl sub_module

cd parent_module
mvn jetty:run -pl sub_module
To complete #jiahut answer:
$ mvn jetty:run --help
(...)
-am,--also-make If project list is specified, also
build projects required by the
list
-amd,--also-make-dependents If project list is specified, also
build projects that depend on
projects on the list
(...)
-pl,--projects <arg> Comma-delimited list of specified
reactor projects to build instead
of all projects. A project can be
specified by [groupId]:artifactId
or by its relative path
Example from Apache Archiva:
mvn jetty:run -pl :archiva-webapp -am

Related

How can I make Maven/Surefire run the tests only in the modules specified by the -pl argument

I have a multi-module Maven projects. And I often run maven for a single module (pl) plus its dependencies (-am):
mvn test -pl module -am
This will start running the tests on all the dependencies as well. Is there a way to tell Surefire to only run the tests in the module/s (the one/s specified by the -pl argument, module in the example above) and skip all the tests in all the modules collected by using the -am option.
Notes:
I cannot use test whitelisting using the -Dtest=... because the package do guarantee that no tests from another module will be executed.
If I don't use the -am option, the build will fail because of the dependencies from the same project that will not be found (and since I am in a Dockerized environments, I don't have the luxury of the cached artifacts in the .m2/repository)
I have applied the following sed workaround in my scripts to solve this problem. Basically, I add the <skipTests>true</skipTests> configuration for the maven-surefire-plugin in all modules of my project with the exception (hence the git checkout command) of my current module (denoted below by variable MAVEN_MODULE):
echo "==> Forcibly disabling of tests in all dependency modules"
for pom in */pom.xml
do
sed -i '/<plugins>/a <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><configuration><skipTests>true</skipTests></configuration></plugin>' $pom
done
git checkout "${MAVEN_MODULE}"
where the sed command adds the following XML fragment in the <plugins> section of each child module pom.xml file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
I solved this issue with profiles and properties.
parent pom.xml,
properties
skip.test - to skip surefire and/or failsafe plugin.
skip.x.test - x is one of modules, define this for each sub-modules.
For example,
<properties>
<skip.tests>false</skip.tests>
<skip.x.tests>false</skip.x.tests>
<skip.y.tests>false</skip.y.tests>
<skip.z.tests>false</skip.z.tests>
</properties>
plugin configs
Put this element into surefire and/or failsafe plugin execution.
<skipTests>${skip.tests}</skipTests>
For example,
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
</configuration>
<executions>
<execution>
<id>default-test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skipTests>${skip.tests}</skipTests>
</configuration>
</execution>
</executions>
</plugin>
profiles
Define a profile to enable tests for only the specified module. You need this for each module.
For example,
module pom.xml
properties
In module x, define this to override the skip.tests property.
<properties>
<skip.tests>${skip.x.tests}</skip.tests>
</properties>
command
maven test -pl x -am -Dtest.x

Run mvn spring-boot:run from parent module?

I have a multi-module maven project like this:
my-parent
--my-domain
--my-service
--my-app <<< this is a Spring Boot module
I want to run mvn spring-boot:run command directly from the parent module without having to cd into the 'my-app' directory first.
I figure this is related to configuration of the spring-boot-maven-plugin but I can't seem to get it right.
I have tried the following:
Use spring-boot-starter-parent and otherwise default config with spring-boot-maven-plugin included in plugins section of my-app.
Running mvn spring-boot:run from the parent results in:
Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.4.2.RELEASE:run (default-cli) on project my-parent: Unable to find a suitable main class, please add a 'mainClass' property -> [Help 1] in the parent module
Do NOT use spring-boot-starter-parent.
Define spring-boot-dependencies in depManagement as described elewhere. Define spring-boot-maven-plugin in pluginManagement section of my-parent and include the plugin in plugins section of my-app module.
Running mvn spring-boot:run from the parent results in same error as #1:
Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.4.2.RELEASE:run (default-cli) on project my-parent: Unable to find a suitable main class, please add a 'mainClass' property -> [Help 1]
Do NOT use spring-boot-starter-parent.
Define spring-boot-dependencies in depManagement as described elewhere. Define spring-boot-maven-plugin in plugins section of my-app.
Running mvn spring-boot:run from the parent results in:
No plugin found for prefix 'spring-boot' in the current project and in the plugin groups
In all cases described above, running mvn spring-boot:run from the my-app directory works fine.
I figure there should be a way to make this work. In a traditional non-Boot Spring project it was fairly simple to configure tomcat7 plugin such that i could run mvn tomcat7:run-war from the parent and the webapp sub-module would start as expected
You can do it by adding following In parent pom:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
And in your
In my-app (Spring Boot module) pom:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<skip>false</skip>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
Now you can do execute in project root:
mvn -pl my-app -am spring-boot:run
Additional references:
spring-boot:run hot reload with multi module maven project · Issue #3436 · spring-projects/spring-boot · GitHub: in particular, this comment.
spring-boot maven plugin configuration options:
skip: skips the execution of sprint-boot:run [default: false]
fork: Flag to indicate if the run processes should be forked [default: true]
see spring-boot maven plugin parameters
maven options:
-pl, --projects: Comma-delimited list of specified reactor projects to build instead of all projects. A project can be specified by [groupId]:artifactId or by its relative path
-am, --also-make: If project list is specified, also build projects required by the list
see maven CLI options

Run two maven modules using mvn tomcat7:run

I've got the following project layout:
web_root
- pom.xml -> packaging: pom
- web_relay
- pom.xml -> packaging: war
- src/...
- web_service
- pom.xml -> packaging: war
- src/...
My web_root's pom.xml has is the superproject and contains two modules: web_relay and web_service.
For reasons unknown someone split these projects rather arbitrarily. I've been trying to merge these projects under one maven superproject.
I can run each of the web_relay and web_service projects using mvn tomcat7:run. However, I need both running on the same tomcat server. When I run tomcat7:run on web_root, however, it only runs the tomcat server for one of the two modules.
How can I get mvn tomcat7:run to run both wars?
The approach from How to use maven plugin tomcat7:run with multiple contexts (WARs)? works only if I mvn install my dependencies separately and don't include them as modules. If I do include them as modules, mvn will just run tomcat7:run in the first module it finds.
Run the war's from a dummy module, listing all dependencies as 'webapps'.
I.e. in the individual pom's, use:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
And make a new module that launches all dependencies at once
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<webapps>
<webapp>
<groupId>com.company</groupId>
<artifactId>webapp-1</artifactId>
<version>1.0</version>
<type>war</type>
</webapp>
[Add more]
</webapps>
As an alternative, and maybe a better solution in the long run, package all web applications in a single EAR (enterprise archive: https://maven.apache.org/plugins/maven-ear-plugin/), so you can also deploy them in production in a single action.
Tomcat7 does not support EAR deploys, but TomEE does: http://tomee.apache.org/maven/run-mojo.html
And JBoss, too: https://docs.jboss.org/jbossas/7/plugins/maven/latest/run-mojo.html

Clover code coverage with multi module project

I'm trying to configure clover with maven.
In parent pom file the lover configuration is as fallowed:
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-clover2-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<licenseLocation>c:\clover.license</licenseLocation>
<reportDescriptor>C:\clover-report.xml</reportDescriptor>
<includesTestSourceRoots>false</includesTestSourceRoots>
</configuration>
</plugin>
I have multi module project look like this:
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
</modules>
and running clover by:
mvn clover2:setup test clover2:aggregate clover2:clover
The problem is clover is building clover.db only for the first module (module1) and not for the rest modules .
What should I do in order to make clover go over all modules?
I have also tried it without aggregate without success.
I guess that your last two other modules were compiled before and as a consequence javac did not recompile sources instrumented by Clover. Try to add the "clean" goal:
mvn clean clover2:setup test clover2:aggregate clover2:clover

tomcat-maven-plugin with multi module and war overlay

I have a maven war project (call it projectA) that depends on another maven war (call it projectB). They get integrated using an overlay with the maven-war-plugin. Both projects have the same parent and the same aggregator (different from the parent). I can package the final war successfully without any issue. This is the command I'm running to do that (I'm at the aggregator level when running mvn):
mvn -am -pl projectA package
The reactor build order is parent ➡ projectB ➡ projectA and all is fine.
I'm now trying to use the tomcat-maven-plugin in this build. So I added the tomcat-maven-plugin in the parent pom pluginManagement section and used it in the projectA pom. I'm launching tomcat with:
mvn -am -pl projectA tomcat:run
The reactor build order remains the same. But the tomcat execution is run on projectB (which is also a war) and not on projectA. Actually, projectA build is not even reached.
I've tried with both the org.codehaus.mojo.tomcat-maven-plugin v1.1 and org.apache.tomcat.maven.tomcat6-maven-plugin v2.1, I've found the same behavior.
How can I make tomcat run the final projectA?
Note: The project dependencies are in fact a bit more complicated and there are other sub-projects involved (jars), that's why I'm calling maven with -am (also make).
Ok, so I found a solution. It is to disable the maven-tomcat-plugin for the pojectB, this answer is based on this other question.
Linking the plugin to a specific phase
First I had to link the maven-tomcat-plugin to a phase of my build cycle, so that it is called even if I don't call the plugin directly from the CLI, obviously I choose the integration-test phase. I can now run mvn integration-test -pl projectA to have tomcat being launched with the just build war.
This is how the plugin is declared in the parent:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>run-war</id>
<!-- We link this plugin to some non default phase so that we can disable it in some modules. -->
<phase>integration-test</phase>
<goals>
<goal>run-war</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
and in projectA I just make use of it as declared in the parent:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
</plugin>
</plugin>
</build>
Deactivating the plugin in projectB
Then, in projectB, I link the same plugin (with the same id) to a null/void/empty phase, which ends up disabling the plugin for this project when built for this integration-test phase:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat6-maven-plugin</artifactId>
<executions>
<execution>
<id>run-war</id>
<!-- We don't want this plugin to be called from another module build -->
<phase/>
</execution>
</executions>
</plugin>
</plugins>
</build>
With that setup, I can now do a complete build (both projectB, projectA and other dependencies) and launch tomcat with the resulting war in a single run:
mvn -am -pl projectA clean integration-test

Resources