Copy all maven dependencies from children pom to directory - java

I'm trying to copy all the dependencies of a project and its sub-modules to a specific folder (lets say parent/target/lib)
the project is something like this:
parent
|- module1
|- module2
|- module3
|- module3.1
|- module3.2
|- module4
in my understanding the only way to do so is by using maven copy-dependency in each sub-module as so:
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${parent.dir}/target/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<excludeGroupIds>xerces</excludeGroupIds>
<excludeArtifactIds>junit,testng,easymock</excludeArtifactIds>
</configuration>
</execution>
I'm having multiple issues with this however:
the lib folder will contain all versions of an artifact (i want only latest)
for each include/exclude rule all the poms need to be updated (there are a lot)
Isn't there something that works together with dependency:list to get all dependencies, keep the latest and copy them to my /lib folder?

I ended up using the assembly plugin in a new sub-project as follows:
parent
|- module1
|- module2
|- module3
|- module3.1
|- module3.2
|- module4
|- assembly-module
The assembly-module calls the maven-assembly-plugin (pom.xml):
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptor>src/assembly/bin.xml</descriptor>
<finalName>module-assembly</finalName>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
finally my assembly file looks like this (assembly-module/src/assembly/bin.xml)
<id>bin</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<scope>runtime</scope>
<useProjectArtifact>false</useProjectArtifact>
<includes/>
<excludes>
<exclude>org.eclipse.jdt:core</exclude>
</excludes>
</dependencySet>
</dependencySets>

Related

Maven Assembly Plugin - Include classes from another module

I have a multimodule project and am trying to generate an assembled file in SubProject2 that includes some of its classes plus some DTOs defined in SubProject1. However, Proc.jar file only has Proc.class and com\myproy\spr\dto*.class, whereas SubProject1's files (com\myproy\dto*.class) are not included and cannot come up with a way to make it work.
Projects' layout:
Parent
|-pom.xml
|
SubProject1
|-pom.xml
|-src\main\java\com\myproy\dto
|-src\main\java\com\myproy\util
|
SubProject2
|-pom.xml
|-src\assembly\def.xml
|-src\main\java\com\myproy\spr
|-src\main\java\com\myproy\spr\dto
def.xml:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0
http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>Proc</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/classes</directory>
<includes>
<include>com/myproy/spr/Proc.class</include>
<include>com/myproy/spr/dto/*.class</include>
<include>com/myproy/dto/*.class</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
SubProject2->pom.xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4.1</version>
<executions>
<execution>
<id>distro-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/assembly/def.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
Correct me if I understand you incorrectly. You want some specific functionality which is in the SubProject1. And you want only this functionality (not more) and you can not include the whole SubProject1 as dependency.
So maybe, if I understand it correctly, you can extract this functionality in another project (something like Commons), and add it as dependency in SubProject1 and SubProject2.
Why don't add the project as a jar dependency ?¿.

Including a synthetic file as javadoc artifact in a Maven build

I am building a multimodule project with Maven where one module represents the shaded version of the other module:
parent
|- base
|- base-shaded
The base module contains all my source files but with dependencies I want to import into my own namespace. This shaded module is described by my base-shaded module which basically only contains a POM which configures a dependency on base and the Maven Shade plugin.
This works fine. The Shade plugin includes all the dependencies and creates a shaded artifact, including a source artifact. However, I am missing a javadoc artifact which is not created by the Shade plugin. Therefore, I attempted to copy the base module's javadoc artifact. However, the release:release goal ignores these artifacts which prevents me to deploying to Maven Central. Still, I managed to include copy these files and include them in install target.
Is there a canonical way of including a non-assembled file in a build? I start to think that I might be the wrong approach.
Here is the plugin configuration of my base-shaded POM. Sorry that it is so much, but in the end, it is Maven XML:
<!-- Shade dependencies -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${version.plugin.shade}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createDependencyReducedPom>true</createDependencyReducedPom>
<dependencyReducedPomLocation>
${project.build.directory}/dependency-reduced-pom.xml
</dependencyReducedPomLocation>
<createSourcesJar>true</createSourcesJar>
<shadeSourcesContent>true</shadeSourcesContent>
<relocations>
<relocation>
<pattern>${shade.source}</pattern>
<shadedPattern>${shade.target}</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
<!-- Copy dependency version's javadoc artifacts -->
<plugin>
<groupId>com.github.goldin</groupId>
<artifactId>copy-maven-plugin</artifactId>
<version>${version.plugin.copy}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<resources>
<resource>
<targetPath>${project.build.directory}</targetPath>
<file>
${project.basedir}/../base/target/base-${project.version}-javadoc.jar
</file>
<destFileName>base-${project.version}-javadoc.jar</destFileName>
</resource>
<resource>
<targetPath>${project.build.directory}</targetPath>
<file>
${project.basedir}/../base/target/base-${project.version}-javadoc.jar.asc
</file>
<destFileName>base-shaded-${project.version}-javadoc.jar.asc</destFileName>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<!-- Because the javadoc files are copied manually, they must be installed manually as well -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<id>install-javadoc</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
<classifier>javadoc</classifier>
<file>${build.directory}/base-shaded-${project.version}-javadoc.jar</file>
</configuration>
</execution>
<execution>
<id>install-javadoc-asc</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<packaging>jar.asc</packaging>
<classifier>javadoc</classifier>
<file>${build.directory}/base-shaded-${project.version}-javadoc.jar.asc</file>
</configuration>
</execution>
</executions>
</plugin>
Of course, there is a plugin for this task, the build-helper-maven-plugin.
We use something like the following to attach the javadoc produced by the unshaded module into the shaded module
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>attach</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>../unshaded-module/target/unshaded-module-${project.version}-javadoc.jar</file>
<type>jar</type>
<classifier>javadoc</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>

Specify common resources in a multi-module maven project

Is there any way to share resources between modules of a parent project in Maven? For example, I would like to specify one log4j.properties file for all the modules in a multi-module Maven project.
Generally, I use Eclipse IDE to create the parent project by choosing a general project and then convert it to a Maven project by specifying a packaging of pom. This creates a "clean" project structure without src and etc. folders. I wonder where such a shared resource should be put in this case.
EDIT1: I would like to put the common resources in the parent project.
I'd create one additional "base" module (project), packaging "jar", that contains the common resources in src/main/resources. Then I'd make the other modules depend on that project. Now they see the common resources on their classpaths.
Antoher possibility is to use a remote resource bundle. You would be able to configure it in the parent project. In this example I wanted to copy some files just for tests. If you use this you will need to create the bundle in another project.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.5</version>
<configuration>
<resourceBundles>
<resourceBundle>es.sca:myBundle:1.0.0</resourceBundle>
</resourceBundles>
<attachToMain>false</attachToMain>
<attachToTest>true</attachToTest>
<appendedResourcesDirectory>${basedir}/src/test/resources</appendedResourcesDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
Another way, put in your project root pom:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<!-- don't propagate to child poms -->
<!-- this will only execute in root pom -->
<inherited>false</inherited>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<!-- don't add classifier -->
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugins>
And example of assembly.xml
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>resources</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}/resources/</directory>
<outputDirectory/>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Assembly plugin will generate artifact and attach it to current reactor, so it will be installed and deployed.
No you can use it as standard dependency event in the same pom.
Important is to trigger assembly (proper phase) before another plugin which will use generated artifact.
Eg. You can have in your root pom, bellow configuration will be propagated to all your module:
<plugin>
<artifactId>some-maven-plugin</artifactId>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>goal</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>your.project.groupid</groupId>
<artifactI>your.project.artifactId</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</plugin>
You can see this method in project:
https://github.com/s4u/pgp-keys-map resources directory is shared by all module.
Yes, it seems as a possible solution. But I was interested whether it
is possible to specify these resources in the parent project (without
introducing additional module) since the parent project specifies all
the common dependencies and Maven configurations for the child
modules, I think that the parent project is the most suitable place
also for the common resources.
In case of packaging type pom , when goal package specified to manage your shared resources, just add next (check folders) into build section of pom file :
<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}/logconfig</outputDirectory>
<resources>
<resource>
<filtering>false</filtering>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
I think you can just add the resources and/or testResources elements to your pom.
E.g. to access an additional test resource directory add:
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
<testResource>
<directory>../global/src/test/resources</directory>
</testResource>
</testResources>
see Maven - Override test resource folder
I managed it to work like this:
I create a project/assembly/test/resources/META-INF/persistence.xml file, and add this to my pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-test-persistence-xml-resources</id>
<phase>process-test-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/</outputDirectory>
<resources>
<resource>
<directory>${project.parent.basedir}/assembly/</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

Include jar-with-dependencies in separate assembly?

I'm using the maven assembly plugin to package a distributable ZIP archive. However, I would like to include the result of a separate assembly, jar-with-dependencies, inside my final archive. How can I do this? I realize that I could probably just include the JAR manually, but how can I ensure that my custom assembly will run after the JAR assembly?
You can use a multimodule project for that:
parent
|- ...
|- jar-with-dependencies-module
|- final-zip-module
In the jar-with-dependencies module, you assemble the "uber-jar" with all dependencies. The build configuration in the POM should look something like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
In the final-zip-module you can add the jar-with-dependencies as a dependency and use it in the assembly descriptor for the ZIP file. The POM would look something like this:
<project>
...
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>jar-with-dependencies-module</artifactId>
<version>1.0.0-SNAPSHOT</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
And the assembly descriptor would look something like this:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>final-assembly</id>
<formats>
<format>zip</format>
</formats>
<dependencySets>
<!-- Include the jar-with-dependencies -->
<dependencySet>
<includes>
<include>com.example:jar-with-dependencies-module:*:jar-with-dependencies</include>
</includes>
<useProjectArtifact>false</useProjectArtifact>
<!-- Don't use transitive dependencies since they are already included in the jar -->
<useTransitiveDependencies>false</useTransitiveDependencies>
</dependencySet>t>
</dependencySets>
</assembly>
Because of the dependency to jar-with-dependency-module, maven will build the final-zip-module always after your uber-jar was built.

multiple src/main/resources folders without profiles (I wish to build multiple versions at once)

I'm working on trying to have my project automatically build two different versions of a project. What I have done is I have added two different plug-in executions as follows
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>exploded</goal>
</goals>
</execution>
</executions>
<configuration>
<resources>
<resource>
<directory>src/main/resources/first</directory>
</resource>
</resources>
<webappDirectory>${webappDirectory}</webappDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>war</goal>
</goals>
</execution>
</executions>
<configuration>
<resources>
<resource>
<directory>src/main/resources/second</directory>
</resource>
</resources>
<webappDirectory>${project.build.directory}/deployment</webappDirectory>
</configuration>
</plugin>
It builds both webappDirectories and it created the war file as expected, but the resources doesn't get included correctly (it seems to ignore the resource definitions above).
I am guessing its because I am doing this in the wrong phase, at what phase do I need to override the default resources directory?
(please notice, I do not wish to have two different profiles, I want to have both done at once)
I have wrote an blog entry exactly about that problem but the essence is about to have the maven project (in your case the war module) with the following structure:
.
|-- pom.xml
`-- src
|-- main
| |-- java
| |-- resources
| |-- environment
| | |-- test
| | | `-- database.properties
| | |-- qa
| | | `-- database.properties
| | `-- production
| | `-- database.properties
| `-- webapp
The most important thing is to create the different configuration via the maven-assembly-plugin with a configuration like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>test</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/test.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>qa</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/qa.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>production</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/production.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
what you also need are assembly descriptors like the following:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>test</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<outputDirectory>WEB-INF</outputDirectory>
<directory>${basedir}/src/main/environment/test/</directory>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Of course you have to name them accordingly and obviously you have to change the directory within the descriptor as well. Based on that it is now possible to create multiple artifacts (in your case war files) with different configurations during the package cycle. So you simply call your project build via:
mvn clean package
Finally i recommend not to use the src/main/resources folder, cause that folder should be used for production information which does not change for the different configuration. Furthermore the src/test/resources will be used for the test resources.

Categories

Resources