Build multiple artifacts with different classifiers at once - maven

W want my maven project to produce three artifacts with different classifiers at once. I know that I can produce it with modules etc. This is actually a resources project that I want to produce configuration for DEV, STAGE and PROD environment.
What I want to have is to run mvn:install once and have my.group:resources:1.0:dev, my.group:resources:1.0:stage and my.group:resources:1.0:prod in my repo.

This can be done without profiles if you specify multiple plugin executions and resource filtering.
Create a properties file for each version in ${basedir}/src/main/filters (e.g. prod.properties, dev.properties) holding appropriate values for each environment.
Turn on filtering for your resources:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
Now add the resource plugin executions. Note the different filter file and output directory.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>default-resources</id>
<phase>process-resources</phase>
<goals>
<goal>resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/dev</outputDirectory>
<filters>
<filter>${basedir}/src/main/filters/dev.properties</filter>
</filters>
</configuration>
</execution>
<execution>
<id>prod</id>
<phase>process-resources</phase>
<goals>
<goal>resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/prod</outputDirectory>
<filters>
<filter>${basedir}/src/main/filters/prod.properties</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
Finally, the jar plugin; note classifier and input directory:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>default-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>dev</classifier>
<classesDirectory>${project.build.outputDirectory}/dev</classesDirectory>
</configuration>
</execution>
<execution>
<id>jar-prod</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>prod</classifier>
<classesDirectory>${project.build.outputDirectory}/prod</classesDirectory>
</configuration>
</execution>
</executions>
</plugin>
Running mvn clean install should produce the properly filtered resources in artifacts with dev and prod classifiers like you want.
In the example, I used execution IDs of default-resources and default-jar for the dev versions. Without this you would also get an unclassified jar artifact when you build.

Just an FYI - put the version number in there to make sure you have the version supporting custom filters. In maven 3 I set mine up like this for example. Without version it didn't work.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
...
</plugin>

Related

How to execute a maven plugin twice with different property

I would like to build from a maven pom running two sequential executions of the same plugin, in the same phase differing only by a single property, which will result in two different archives being created. Since the configuration is rather complicated, I'd rather NOT copy it just to change one value, which would create a maintenance nightmare. If it was somehow possible to define such a property in the <executions> section of the plugin config, I could avoid this headache.
Question: Is this possible and if so how?
Update: Two answers have mentioned using multiple executions and one of them mentions that you can have separate configurations in each execution. But given that the majority of my configuration is constant between the two executions, can I have one configuration on the plugin level and also have configuration sections in each execution for the parts that are different?
Given the simple Maven Source Plugin configuration (as an example) you have a shared configuration across all of its executions (outside the executions element) and then a custom configuration per each execution, for the same phase, as requested by your question:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.4</version>
<configuration>
<includePom>true</includePom>
</configuration>
<executions>
<execution>
<id>test-id1</id>
<phase>verify</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<finalName>aaa</finalName>
</configuration>
</execution>
<execution>
<id>test-id2</id>
<phase>verify</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<finalName>bbb</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The configuration entry <includePom>true</includePom> will in this case be merged with the custom configurations of each execution and as such centralize the common configuration as plugin generic configuration.
For more details on the different level of configurations, you can check official Maven documentation, here, in particular the example "Configuring compile to run twice". Further details are also available on the official POM documentation, here, Plugins section.
You need to create a different execution (still bound to the same phase)
To avoid duplication of the config, you can put the <configuration> outside the <execution> element and then in the 2 executions, you only define the property that is different.
Taken from the maven docs:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-myquery-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>execution1</id>
<phase>test</phase>
<configuration>
<url>http://www.foo.com/query</url>
<timeout>10</timeout>
<options>
<option>one</option>
<option>two</option>
<option>three</option>
</options>
</configuration>
<goals>
<goal>query</goal>
</goals>
</execution>
<execution>
<id>execution2</id>
<configuration>
<url>http://www.bar.com/query</url>
<timeout>15</timeout>
<options>
<option>four</option>
<option>five</option>
<option>six</option>
</options>
</configuration>
<goals>
<goal>query</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
</project>
You create two <execution> elements within the <plugin> declaration. Each <execution> element can have it's own <configuration> section.
I wanted to create a jar and a put in in a zip file with other config files
This worked for me
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>build-jar-with_dep1</id>
<phase>package</phase>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<finalName>${buildversion}</finalName>
<finalName>finalname</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<goals>
<goal>assembly</goal>
</goals>
</execution>
<execution>
<id>build_zip1</id>
<phase>package</phase>
<configuration>
<descriptor>src/assembly/bin.xml</descriptor>
<finalName>${buildversion}</finalName>
<finalName>finalname</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

Generated sources being compiled twice

Using Eclipse Luna with m2eclipse, I have a parent Maven project (facturas_root) and two Maven modules inheriting from it (sharepoint_ws and api_sharepoint).
sharepoint_ws was to be used only to generate JAXWS classes to connect to the Sharepoint WebServices, so I downloaded the related WSDL and included those as resources of the project. At generate-sources phase, it works correctly and generates the sources in target\generated-sources\ws-consume\mypackage\.
Now, the issue is that I made api_sharepoint import the sharepoint_ws dependency, but it does not detect any class. I assumed that it was because the generated classes were not at src/main/java, so I added a plugin to copy them there. Now, the problem is that at the compile phase of sharepoint_ws, it finds twice the source file of each class and throws an error.
My pom.xml -> build
<plugins>
<!-- clean /src/main/java and /target/generated-sources -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.6.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<filesets>
<fileset>
<directory>${basedir}/src/main/java/es</directory>
</fileset>
<fileset>
<directory>${basedir}/target/generated-sources</directory>
</fileset>
</configuration>
</execution>
</executions>
</plugin>
<!-- generate jaxws -->
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>maven-jaxws-tools-plugin</artifactId>
<version>1.1.2.Final</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>wsconsume</goal>
</goals>
<configuration>
<wsdls>
<wsdl>${basedir}/resources/lists.wsdl</wsdl>
</wsdls>
<targetPackage>es.ssib.otic.facturas.sharepoint_ws</targetPackage>
<outputDirectory>${basedir}/target/generated-sources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- copy sources -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-filtering</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/src/main/java</outputDirectory>
<resources>
<resource>
<directory>${basedir}/target/generated-sources/wsconsume</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
In order to try to exclude target/generated-sources I have addded this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<configuration>
<excludes>
<exclude>**/target/generated-sources/*.java</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
As stated above, I do comment the "copy" plugin, the module depending on sharepoint_ws does not have any ot its classes available; I do use it I get errors in the tune of
[ERROR] /C:/Users/s004256/workspace/facturas_root/sharepoint_ws/src/main/java/es/ssib/otic/facturas/sharepoint_ws/DeleteList.java:[34,8] duplicate class: es.ssib.otic.facturas.sharepoint_ws.DeleteList
for each generated list.
In the first place, I recommend you'd better declare target/generated-sources as a source folder, instead of copying files here and there:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-source</id>
<phase>initialize</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
This should be enough to make Maven compile the target/generated-sources/*.java and package them all in the library, and also for Eclipse to recognize target/generated-sources as a source directory (after you execute Maven/Update Project).
By the way: You should take care of binding the plugins to a phase in the correct order: If you bound all tasks to "generate-sources", you have no gurantee about in which order will they be executed. And the same goes for the "compile" phase: You have to set properly the source folders, with its inclusions and exclusions, before the compile phase.
Take a look a the Default Maven Lifecycle and try to chose different, sequential phases for your tasks.

Move a config file into etc folder(of Karaf) when a (Maven)bundle is deployed

I want to move a cfg file into the etc folder of karaf whenever a bundle is deployed.
the cfg file is in under src/main/resource .i tried the following in the pom but its not working.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<phase>deploy</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Using env.test.properties</echo>
<copy file="src/main/resources/test.cfg" tofile="${env.KARAF_HOME}/etc/test.cfg"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
How can i do it ?
One of the solution could be:
- put your test.cfg file in a more specific folder. (eg: src/main/resources/cfg)
- use the maven resources plugin
This is a working example based on the maven phase generate-resources (replace that phase by deploy in your case):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-to-karaf</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/resources/cfg</directory>
<filtering>true</filtering>
</resource>
</resources>
<outputDirectory>D:\apache-karaf-3.0.1\etc\</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>

Creating directory structure for application with maven

How can I tell maven to create a particular directory structure and to put jar files in certain places?
For example I want to put put some jars in a directory called plugins which are loaded at runtime.
Is that possible? Or am I missing the principles behind maven?
It looks like your jars is your project dependency, so to copy all dependencies at plugins folder use next:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-alldeps</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/plugins</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<excludeTransitive>false</excludeTransitive>
</configuration>
</execution>
</executions>
</plugin>
When your project use jars like resources, use maven resource section or next plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-config-files</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/plugins/</outputDirectory>
<resources>
<resource>
<filtering>false</filtering>
<directory>${project.basedir}/jars/</directory>
<includes>
<include>file1.jar</include>
<include>file5.jar</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

Maven: use jar from URL as a source for resources

Dealing with a legacy project, I have the need to load text resources from a jar at an URL.
The text resources will be then filtered and included in the output; those resources come from a released artifact.
From resource-plugin I see it is only possible to give a number of directories; would it be possible to load resources as I need?
I want to do somthing like this, but using a remote jar instead of the oher project in the workspace:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}</outputDirectory>
<resources>
<resource>
<directory>../<another project on the same workspace>/src/main/filtered-resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Remote resource plugin, as suggested in one of the answer doesn't work because no file from the imported bundle ends up in target; there is no way I can produce the original bundle using remote resource plugin (it's a legacy projetc still in use and completely out of my control).
I think the Maven Remote Resources Plugin will suit your needs.
EDIT:
Snippet obtained from the usage page of the plugin. That XML fragment will attach the plugin to the generate-sources phase (choose a different one if it doesn't fit your needs), will download the apache-jar-resource-bundle artifact and uncompress its contents into ${project.build.directory}/maven-shared-archive-resources.
For better results is recommended that the resources artifact had been created using the bundle goal of the same plugin.
<!-- Turn this into a lifecycle -->
<plugin>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>process-remote-resources</id>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<resourceBundles>
<resourceBundle>org.apache:apache-jar-resource-bundle:1.0</resourceBundle>
</resourceBundles>
</configuration>
</execution>
</executions>
</plugin>
EDIT 2: Alternative Solution using AntRun
If your artifacts don't suit Maven needs and you need something more customized, then using AntRun plugin you could get it somehow:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>download-remote-resources</id>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<get src="URL of the resource" dest="${project.build.directory}" />
<unzip src="${project.build.directory}/filename.[jar|zip|war]" dest="${project.build.directory}/${project.build.finalName}" />
</target>
</configuration>
</execution>
</executions>
</plugin>

Resources