Using profiles to exclude WAR modules from 'mvn install' - maven

My parent pom defines 7 modules, 5 of which are dependency jars, and two are wars that depend on those jars.
Question: Is it possible to use maven profiles (or another solution) to define which modules are included when mvn install is run against the parent pom to exclude the two war packages?
I would then like to have a different profile (or another solution) to package the two wars. If that profile is run, the dependency jar modules should be rebuilt and installed only if they are missing from the repository.

You could use the build-helper-maven-plugin in your parent pom.xml file to create a new property based on the packaging (at runtime it would change from pom for the parent, to jar and war for the modules). This new propery could then be used to skip the maven-install-plugin dynamically.
A simple example:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<id>build-helper-regex-is-packaging-war</id>
<phase>validate</phase>
<goals>
<goal>regex-property</goal>
</goals>
<configuration>
<name>only.when.war.is.used</name>
<value>${project.packaging}</value>
<regex>war</regex>
<replacement>true</replacement>
<failIfNoMatch>false</failIfNoMatch>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<configuration>
<skip>${only.when.war.is.used}</skip>
</configuration>
</plugin>
Doing so, the dynamic ${only.when.war.is.used} property would be set to true only when project.packaging would have value war and as such effectively skip the maven-install-plugin executions via its skip option.
You could then move this behavior to a profile and have different settings for jar and war, keeping them in a common place: the root pom.xml, thanks to their dynamic behavior.
Concerning the ability to detect whether an artifact has already been installed or not, there is no such an option on the official plugin documentation and I don't think you could have such a behavior by simply using the plugin.
You could however use the maven profile activation mechanism in case a file is missing (the installed file) and activate the profile accordingly.
You could have in a dynamic way (based only on standard properties) the following approach:
<profiles>
<profile>
<activation>
<file>
<missing>${settings.localRepository}/${project.groupId}/${project.artifactId}/${project.build.fileName}.${project.packaging}</missing>
</file>
</activation>
...
</profile>
</profiles>

Related

Maven - How to extract a dependency inside another ZIP dependency?

I have a maven project.
Inside that project, I have a .zip dependency that carries a jar and I need to extract that jar out of the zip dependency and have maven use the jar as a dependency. I can currently download and unpack the zip but, cannot figure out a way to add the unpacked jar as a dependency for the project during the build process.
Here is what I'm currently doing for unpacking:
<dependency>
<groupId>com.bar</groupId>
<artifactId>foo</artifactId>
<version>${foo.version}</version>
<type>zip</type>
</dependency>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>validate</phase>
<configuration>
<includeGroupIds>com.bar</includeGroupIds>
<includeArtifactIds>foo</includeArtifactIds>
<outputDirectory>${basedir}/target</outputDirectory>
<type>jar</type>
</configuration>
</execution>
</executions>
</plugin>
I read up on some other posts that you could try adding the jar to the class path using this.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>${basedir}/target</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
Even doing so I was still unable to reference the packages in foo.jar in my project.
Can someone help me?
For maven to use it without subtly breaking stuff elsewhere, you must install the jar into your local repository.
I would suppose that a combination of unpacking the zip file in target/ and then invoking install:install-file on the resulting jar could do what you need. I asked some years back how to integrate that in a normal build - you might find the answer relevant. Multiple install:install-file in a single pom.xml
Let's assume that, after unpacking the zip, you have foo.jar in your module's target folder: ${project.build.directory}/foo.jar
Having this in place, you can then declare a System Dependency pointing to that jar, e.g.
<dependency>
<groupId>foo</groupId>
<artifactId>foo.jar</artifactId>
<systemPath>${project.build.directory}/foo.jar</systemPath>
</dependency>
Tip: if you dont want to delete/re-download the jar each time you do a clean (some IDE will complain the the jar is not always present) just download it once in the ${project.basedir}.
To download the jar once, you can put your "unpack" execution in a profile that gets activated only when the jar is missing.
<profiles>
<profile>
<activation>
<file>
<missing>${project.basedir}/foo.jar</missing>
</file>
</activation>
...
</profile>
</profiles>
Some time ago, I've faced the same problem. I had a zip file as my dependency, and during the build process I need to extract it and separate the content inside my generated package.
I don't know what are you using to deliver your project, but at that time I've used the maven-antrun-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>2.6</version>
</plugin>
With this, I've used the tag unzip inside my target configuration. As you can see here or here. I just don't recommend you to use the task tag as they're using, you'd better prefer the target tag.
Hope it helps you.

How to download the souce of jars to custom location in maven?

This is follow up post of How to get all the specified jars mentioned in the pom.xml and transitively dependent jars?
Except that I am looking to download the source of the both dependent and transitively dependent jars to custom mentioned location.
I have tried following command but it didn't works.
mvn dependency:sources -DoutputDirectory=.../
It didn't worked.
mvn dependency:sources dependency:copy-dependencies -DoutputDirectory=.../
It didn't worked.
The source jar is normally available via Maven using a classifier, so that for the same Maven coordinates (GAV, groupId, artifactId, version) you can have more than one artefact related to the same build (i.e. default application/library jar, sources jar, test sources jar, javadoc jar, etc.), as also explained in another SO answer. The standard classifier for sources is sources, created by the Maven Source Plugin.
The copy-dependencies can be configured to fetch a certain classifier via the classifier option.
So in your case, to get the sources of your dependencies to an external folder, you can invoke the command as following:
mvn dependency:copy-dependencies -DoutputDirectory=somewhere -Dclassifier=sources
Note the additional -Dclassifier=sources option.
An example of pom configuration to achieve the same is also explained in the official documentation of the Dependency Plugin, using the following snippet:
<project>
[...]
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>src-dependencies</id>
<phase>package</phase>
<goals>
<!-- use copy-dependencies instead if you don't want to explode the sources -->
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<classifier>sources</classifier>
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
<outputDirectory>${project.build.directory}/sources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
[...]
</project>
Beware though that Maven doesn't know about sources, it only knows about artefacts. So if the sources (classified) artefact is not available via its GAV+C, Maven will find it and as such will not download any source.

Change default pom.xml and project layout of Maven

I am just starting using maven and I use Apache Maven Shade Plugin a lot. Is it possible to add these code
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- put your configurations here -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
to default pom.xml. Yes, it can change setting.xml to make this plugin work with all project. But if I have some specific project which will not need this plugin, do I have to rewrite setting.xml again?
Another problem is that is it possible to change project layout of Maven. I use git a lot. Can I add sample .gitignore every time when I run mvn archetype:generate.
For you first issue, I think you can benefit from the parent POM:
http://books.sonatype.com/mvnex-book/reference/multimodule-sect-simple-parent.html
It's a defined POM file in which you put whatever you want. You publish it as a "pom" in your Maven repository and then, you can inherit from it in other projects. It is very convenient to lock dependency verions as well.
Your second issue seems more related to the archetype you are using than maven itself. You will probably have to create your own with a default .gitignore in it.

maven jboss tattletale report

I am trying to add a tattletale report to a maven 2 master POM.
Ideally I only want the report to run once, but it seems to be run with every module compile.
Is it possible to set tattletale into a master POM and only have it run once on the entire code base? If so, can somebody provide the settings for the POM file so that I achieve this.
One way to do something like what you're describing is to put the configuration in a Maven profile in your parent pom. Then you can activate that profile on-demand when you build any of your child modules. For example, if you want a predefined configuration that you can use on any of your war modules, you might do something like this:
<profile>
<id>tattletale-war</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jboss.tattletale</groupId>
<artifactId>tattletale-maven</artifactId>
<version>1.2.0.Beta2</version>
<executions>
<execution>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
<configuration>
<source>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</source>
<destination>${project.build.directory}/reports</destination>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Then activate it when you want at the command line:
mvn clean package -P tattletale-war
Tattletale generates a report based on an artifact, so doesn't that mean a report needs to be made at a Maven module level?
I'm working on a multi-module Maven project, and my plan is to declare the plugin at the top, under and have it declared for each of the modules I want to report on.

change deployed artifact name based on profile

I have in a web application's pom file, a build profile, which does some necessary things (in my code) for qa testing.
I have this code on svn and this code is compiled in Hudson, which deploys artifacts in nexus..
Hudson has two jobs, one for qa profile (-P qa) and one for customers.
What i need is that i change in my qa profile the artifact's name during deploy phase, so that nexus has two different war files, one for qa and one for customer.
I use (after Google search) the following which looks like it does nothing in hudshon!
<profile>
<id>qa</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.5</version>
<configuration>
<classifier>qa</classifier>
</configuration>
</plugin>
</plugins>
</build>
</profile>
any ideas someone?
You actually need to set the "classifier" configuration option on the plugin that's building the package that's being deployed: maven-(ear|ejb|jar|rar|war|shade)-plugin:
For instance, to build a WAR with a qa classifier, you would do the following:
<profile>
<id>qa</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<classifier>qa</classifier>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Also, instead of setting the classifier you could set any of the following (most default to project.build.finalName, so setting that property updates many of these):
General
project.build.finalName
War Plugin
warName
Ear|Jar|Rar|Shade Plugin
finalName
EJB Plugin
jarName
One final note: I never realized this before, but looking over the documentation, it looks like the RAR plugin doesn't support the "classification" option. Shade does support the classifier concept, but does it via the "shadedClassifierName" property.

Resources