How to run jetty:run-war using a war defined by maven coordinates? - maven-2

Background: I'm setting up a functional tests module in a maven project. We use the maven-jetty-plugin for testing.
I've got the jetty plugin set up as described here (to play nicely with the Failsafe plugin), but what I'd like to do is deploy the war artifact from our main web module using jetty (which has just been installed into the local maven repo by the time the functional test module is running).
The jetty plugin's run-war goal has a <webApp> element which takes a string path to a war to deploy. I'd much rather specify the war to deploy using the maven coordinates defined by our web module. Is there any way to do this?
Possible workarounds:
Section 4.13 of "Better Builds with Maven" describes using cargo to deploy a war specified using maven coordinates, but that's serious overkill given that we're using jetty.
More reasonable IMO is using dependency:copy to copy the just-built-and-installed war artifact to a fixed path in the functional tests module's target directory, which I can then provide in the jetty plugin's <webApp> configuration element.

The jetty plugin's run-war goal has a element which takes a string path to a war to deploy. I'd much rather specify the war to deploy using the maven coordinates defined by our web module. Is there any way to do this?
This is not really the maven jetty plugin is supposed to be used, the plugin deploys the war of the current module, what you want to do is not supported by default.
Section 4.13 of "Better Builds with Maven" describes using cargo to deploy a war specified using maven coordinates,
Yes, Cargo can do this in a clean way.
but that's serious overkill given that we're using jetty.
I don't agree. First, the jetty plugin doesn't support what you want to do out of the box (so it may not be the right tool). Second, serious overkill is highly exaggerated, a misconception actually, especially given that cargo requires very little configuration (zero?) for an embedded Jetty.
More reasonable IMO is using dependency:copy to copy the just-built-and-installed war artifact to a fixed path in the functional tests module's target directory
No offense but your whole question sounds a bit like: I have a hammer, it was fine for a nail, can I use it for a screw given that getting a screw driver seems a serious overkill? To answer this question (which is somehow what you are saying), you can use dependency:copy and get the whole thing working with the maven jetty plugin, but this is a hack (and since you're actually not asking any question, I guess you wanted an opinion on this). Of course the final decision belongs to you :)
Just in case, here is how I would implement this with Cargo:
<dependencies>
<dependency>
<groupId>war group id</groupId>
<artifactId>war artifact id</artifactId>
<type>war</type>
<version>war version</version>
</dependency>
...
</dependencies>
...
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<!-- Container configuration -->
<container>
<containerId>jetty6x</containerId>
<type>embedded</type>
</container>
<!-- Configuration to use with the container or the deployer -->
<configuration>
<deployables>
<deployable>
<groupId>war group id</groupId>
<artifactId>war artifact id</artifactId>
<type>war</type>
<properties>
<context>war context</context>
</properties>
</deployable>
</deployables>
</configuration>
<!-- Don't wait, execute the tests after the container is started -->
<wait>false</wait>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
And I don't think that this can be objectively qualified as a "serious overkill".

Related

New at Maven: Using the shade plugin and 3rd party jars

This should be pretty simple, but I can't the around to it. I need to create an uberjar using 3rd party jars. I've already followed these instructions: Including a non-Mavenized dependency so it works with maven-shade-plugin and added them to the local repository. But now what? Every Maven tutorial/example is kinda shady (pun intended) and I just don't know how to edit the .pom file properly in order to make it work.
Besides, I'm confused about the shade "plugin" overall. I mean, I followed the basic Maven tutorials and it went all fine and dandy. But when I look into the shade plugin page, I can't find it to download, except for the source code. I mean, isn't it a plugin? Shouldn't I download the binaries and install it into Maven somehow?
Sorry about the extreme noobish question but, needless to say, I know squat about Maven.
To create your shaded (uber) jar, you just need to declare the shade plugin in your pom.xml.
With regards to installation of the shade plugin, simply declaring it in the plugins section of your pom.xml is all you need do. Maven plugins are not installed manually, but are automatically downloaded by Maven (if not already downloaded; just like dependencies), stored in your local repository, and used whenever a project needs them.
As to using it, much like other plugins, declare it in your pom.xml by adding a <plugin> element with your configuration needs. This plugin does nothing automatically (some do, some don't) - you have to specify which "goal" to execute (think "method of a class"), and in which "phase" (think "step" of the build process). Unless you have strange needs, specify the "shade" goal in the "package" phase (see below).
For more configuration possibilities, see the shade usage page, and their examples (especially selecting contents for uber jar). Here is a simple example which, when you run mvn package, replaces your original jar in the target/ directory with the uber jar. It only includes the runtime dependencies, not the ones used at test time (notice the <scope> element of the junit dependency, which is not included in the uber jar).
<project>
<groupId>com.sample</groupId>
<artifactId>test</artifactId>
<version>1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.sample</groupId>
<artifactId>test-core</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
If you have already downloaded the binaries and installed them into your local Maven repository all that remains is to declare them as dependencies in the POM. If the shade plugin is also declared in the POM a simple "mvn install" should generate a standalone JAR in the target directory.

Maven plugin dependencies are ignored

I created this profile for deploying artifacts on the server via SCP. I know Ant's scp task is optional, therefore I've added the dependencies.
<profiles>
<profile>
<id>remote-deploy</id>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>scp</id>
<phase>install</phase>
<configuration>
<tasks>
<scp .../>
<sshexec .../>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-jsch</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.42</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
However, when I run the profile, I end up with
An Ant BuildException has occured:
Problem: failed to create task or type
scp Cause: the class
org.apache.tools.ant.taskdefs.optional.ssh.Scp
was not found.
This looks like one of Ant's optional components. Action: Check
that the appropriate optional JAR
exists in
-ANT_HOME\lib
-the IDE Ant configuration dialogs
Do not panic, this is a common
problem. The commonest cause is a
missing JAR.
This is not a bug; it is a
configuration problem
Is it possible maven wasn't able to download those dependencies or it just ignores them?
The problem was Maven (2.2.1) didn't download the dependencies. I've found out after I upgraded Maven to version 3. For some reason,the new version downloaded the plugin dependencies and it miraculously started to work.
I have a suspicion the problem was in old version Maven's settings - pluginRepository wasn't configured.
It is likely that maven has downloaded the jars but it is not in ant's classpath. If the objective is to deploy the artifacts using maven, you should probably use Maven Deploy Plugin. What you are doing seems to be a roundabout way.
There is a maven-antrun-plugin bug entry, that could explain why this is happening in Maven-2, they also describe workarounds
In multi-module builds, if there are multiple poms configuring the maven-antrun-plugin, the first(?) seems to win, so that the ones later in the build chain reuse the antrun config from earlier poms, thus missing out on stuff that is different ...
In my problem case, I opted to use Maven-3, where the issue seems to be fixed, instead of workarounds with Maven-2. This had the additional advantage of the build to also speed up - now taking 6min instead of the 10min before.
However, if Maven-3 is not possible for you, I'd try the workarounds...

Maven pom.xml - Project Aggregation

We have a aggregation .pom set up to include several, individual modules, similar to the Maven documentation:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<packaging>pom</packaging>
<modules>
<module>my-module</module>
<module>my-module-2</module>
</modules>
</project>
Is there a way to get the artifacts from the builds (.JAR files) from these two modules into a common 'dist' directory after building? I did not want to adjust to output directory for the individual modules from "my-module/target" since they can be built separately as well.
I'm a Maven new-comer, so I'm sure there's an easy way to do this I'm missing.
Is there a way to get the artifacts from the builds (.JAR files) from these two modules into a common 'dist' directory after building?
The Maven Assembly Plugin can do that, it is very powerful and flexible. But power and flexibility also mean that this is not the most trivial plugin to use. In your case, the idea would be to generate a dir distribution from a moduleSets and you'll have to create a custom assembly descriptor for that.
I suggest starting with chapter 8.2. Assembly Basics of the Maven book and to pay a special attention to the chapter 8.5.5. moduleSets Sections.
After reading more at the links from the other answers, here is what I'm going to try for now:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-jars</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>../src/my-module/target</directory>
<includes>
<include>**/my-module*.jar</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
Not exactly pretty, but while researching the Assembly plug-in for a possible longer term solution, this will do.
i guess maven assembly plugin can do this
As #Pangea said assembly plugin will do it. Just run assembly:assembly goal with appropriately set outputDirectory parameter.
more info at http://maven.apache.org/plugins/maven-assembly-plugin/assembly-mojo.html

Simple Mavenization of existing Ant build files

If you have an existing ant file, what is the best way to convert the project to Maven. I've checked out things like fAnt, but if I'm going to mess with this stuff, I might as well go full-bore for Maven. I expected something to exist that can just start the pom.xml for me based on the existing build.xml, but I haven't found anything yet. Suggestions?
I don't know any good automated way to do such a migration because things may just be too different so I would do it manually, step by step, and keep the existing ant build in parallel of the future new one until the whole migration is done (from both technical and human points of view).
First, refactor the existing Ant build to align it on Maven conventions:
Make things modular: if your existing build is a big monolithic build producing several artifacts from a single source tree, break it down into separate modules, one for each artifact.
Update directory structure: Maven comes with a standard directory layout and, while it is possible to customize this layout (i.e. to configure plugins for another layout), this is not really recommended and is more a source of troubles than benefits. So I'd move existing app sources, configuration files, tests, etc to match Maven's layout (e.g. src/main/java for application sources, etc).
Then, start to create the Maven build:
Create POMs for each module: Create a POM, declare external libraries as Maven dependencies (maybe add them to a corporate repository, using an enterprise repository is a good practice in an enterprise context anyway), add dependencies between modules.
Finalize the multi-modules build: Add parent(s) POM(s) and inheritance/aggregating relationships. Test that there is no regression with the created artifacts.
You could do this work in a separate VCS branch if you don't want to change anything until the work is done and create scripts to move things. And when ready, merge the Maven specific stuff and apply the scripts.
You could run the Ant script from Maven with the maven-antrun-plugin. Your pom.xml would look something like this:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant-nodeps</artifactId>
<version>${ant-nodeps.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>init</id>
<phase>compile</phase>
<configuration>
<tasks>
<!-- Ant code goes here -->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</build>
</project>
That way you can start to move your dependencies into Maven, and reference them in the Ant script like so
${com.foo.bar:my-lib:jar}
Then just start slowly moving pieces of your Ant into pure Maven stuff.

How do I deploy multiple peer webapps from a parent pom

I have a set of web apps that I manage that I am trying to move to maven.
/pom.xml // parent pom
webapp1/pom.xml // configured to point to parent
webapp2/pom.xml // peer of webapp1 and points to parent.
each of the webapps refers to the parent pom, and they both currently have a jetty maven plugin that works.
My question is how do I mount each of the webapps from the parent pom such that mvn jetty:run works in the parent directory?
edit to anwer: Pascal T
The issue is not so much that I'm getting an error when I try and run the command from the root pom, but that I'm not sure how to configure it.
for example the webapp1/pom.xml
looks like:
<project>
...
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
</plugins>
...
</project>
changing to this directory and typing mvn jetty:run works just fine and affords me the ability to hit: http://localhost:8080/webapp1.
However, what I would like would be to be in the parent of webapp1, and run all 'n' webapps from the parent directory. Thus having http://localhost:8080/webapp1, and http://localhost:8080/webapp2 available with one command line parameter.
btw, if the answer involved a tomcat plugin, that would be fine.
EDIT: I've totally edited my first answer now that I have a better understanding of the OP's expectations.
Check out Cargo, a thin wrapper that allows you to manipulate Java EE containers in a standard way.
Actually, there is a tutorial on Cargo's website that demonstrates how to use the Cargo Maven2 plugin to automatically start/stop a container (possibly deploying some deployables to it as it starts), which is what you're looking for from what I've understood.
I'm just not sure that doing this from the parent directory is feasible and if it's a requirement or if it would be ok to do it from another directory. I'll come back on this later. Lets first take a look at the Cargo Maven2 plugin setup.
In your case, you can start with the minimal configuration (that uses Jetty 5.x which is Cargo's default container):
[...]
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
</plugin>
</plugins>
</build>
[...]
If you want to use Jetty 6.x, you'll have to specify <containerId> and <type> in the <container> element:
[...]
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<container>
<containerId>jetty6x</containerId>
<type>embedded</type>
</container>
</configuration>
</plugin>
[...]
Then, add the modules you want to deploy by defining deployables explicitly inside the plugin configuration (refer to the Maven2 Plugin Reference Guide for the details of the configuration) :
<deployables>
<deployable>
<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-alpha</artifactId>
<type>war</type>
<properties>
<context>optional alpha root context</context>
</properties>
</deployable>
<deployable>
<groupId>com.mycompany.myproject</groupId>
<artifactId>myproject-beta</artifactId>
<type>war</type>
<properties>
<context>optional beta root context</context>
</properties>
</deployable>
[...]
</deployables>
With this, you should be able to start Jetty and have your webapps deployed on it with a simple (to run from the project containing the cargo plugin configuration):
$ mvn cargo:start
I'm just not sure that this can work with the parent pom (I wonder if this can lead to cyclic dependencies issues) and I didn't test it. But personally, I'd put all this stuff in the pom of a dedicated project, e.g. in a sibling project of your webapps, and not in the parent pom. I don't think it's a really a big deal and this is IMHO a better setup, especially if you plan to use cargo for integration testing.