Maven Assembly Plugin - Include classes from another module - java

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 ?¿.

Related

Attaching main artifact if built by maven-assembly-plugin

I have issues building my maven project. It requires building two jars - one of them is built by default maven-jar-plugin which just contains the complied class folders of my Java code and the other, customized one made by maven-assembly-plugin in package phase is an executable jar with all the dependency jars added.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-assembly-
plugin:2.2-beta-5:single (executable-jar-generation) on project enhanced-
search: Execution executable-jar-generation of goal
org.apache.maven.plugins:maven-assembly-plugin:2.2-beta-5:single failed: For
artifact {com.fmr.es:enhanced-search:1.0:jar}: An attached artifact must
have a different ID than its corresponding main artifact. -> [Help 1]
I've been following Manually attach main artifact if built by maven-assembly-plugin as reference since the problem is more or less same.
As the answer says, I add the ant-plugin code which overwrites my main jar with the executable one to install on the repository with the package phase.
But before maven even reaches this plugin, the above error crops up. I can't do the vice-versa since there has to be the executable jar created in the first place to overwrite the main one.
Anymore feedback is really appreciated.
The following is the assembly plugin which creates my executable jar along with the assembly.xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<id>executable-jar-generation</id>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>executable-enhanced-search-1.0</finalName>
<descriptors>
<descriptor>assembly-jar.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
<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">
<baseDirectory>/</baseDirectory>
<formats>
<format>jar</format>
</formats>
<fileSets>
<fileSet>
<directory>../../target/classes</directory>
<includes>
<include>**/*</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
</assembly>
The following is the tailored ant task as mentioned in the link I posted above.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy file="../../target/executable-enhanced-search-
1.0.jar" tofile="../../target/enhanced-search-
1.0.jar" overwrite="true" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>

How do you use the maven shade plugin to include only specific classes from a dependency with scope "provided"?

I am using the maven shade plugin to package my application into a jar file. One of my dependencies is to Tomcat:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>7.0.59</version>
<scope>provided</scope>
</dependency>
The scope of this dependency is provided as the container itself will supply its JAR files. However, I do need to add a few single classes from this dependency to my JAR file. I tried adding a filter and specifying the name of the class that is to be added, but it seems that provided dependencies are ignored by the shade plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>org.apache.tomcat:tomcat-catalina</artifact>
<includes>
<include>org/apache/catalina/deploy/LoginConfig.class</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Any ideas how what I need can be achieved?
The configuration setting you need is <useDependencyReducedPomInJar>true</useDependencyReducedPomInJar>. This will create a file named dependency-reduced-pom.xml with the references to the shaded jar(s) removed. You can also use <promoteTransitiveDependencies>true</promoteTransitiveDependencies> if the shaded jars have their own transitive dependencies to add them to the modified pom.
I had the same issue and If I can suggest a solution it would be to use the maven-assembly-plugin which will address your problem :
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<executions>
<execution>
<id>jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>com.mypackage.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
And here is a sample of the assembly.xml which will allow you include "provided" scope artifacts:
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
</dependencySet>
<dependencySet>
<outputDirectory>/lib</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<unpack>false</unpack>
<scope>provided</scope>
</dependencySet>
</dependencySets>
I'am just having classpath issues in the generated artifact in the Manifest file!
I'm not very familiar with this plugin, but the best place for finding solutions to these kinds of problems is to have a look at the plugin/ goal documentation.
I guess the parameter keepDependenciesWithProvidedScope is what you are looking for.
I had the same issue, but I found we misunderstood how this plug-in works. If some dependencies are bundled into the shaded jar, they will be removed from the dependencies in the pom.xml in the shaded jar. So you should change nothing, just left their scope runtime.

Using Maven to create Javadocs as a zip file instead of a jar file

I am trying to figure out how to create a zip file of my Javadocs instead of a jar file using Maven. I am currently creating a jar file using the maven-javadoc-plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>attach-javadoc</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
I looked at the goals listed here but found nothing helpful to this end. Is this possible using maven-javadoc-plugin or must some other plugin be used?
You need to use maven-javadoc-plugin in combination with maven-assembly-plugin to package the generated docs in a zip. First, only generate the apidocs using javadoc:javadoc goal, but don't package it. This generates the docs in ${project.build.directory}/apidocs by default.
Then, use maven-assembly-plugin to package these docs as follows:
Add maven assembly plugin:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>docs-assembly</id>
<phase>package</phase>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assemble.xml</descriptor>
</descriptors>
</configuration>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Now, configure maven assembly plugin:
<?xml version="1.0" encoding="UTF-8"?>
<assembly>
<id>${project.build.finalName}</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}/apidocs</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>

Maven building for different environments

I have a Java project that currently builds nicely with Maven. But, I'm using an Ant script to do other tasks that I think Maven could also do. To simplify the build workflow, I'd like to get Maven doing everything I need. All this is automated with Jenkins.
The challenge is that I want Maven to build a single artifact and deploy it to multiple environments on-demand via command line. Currently, I do this by building with Maven, then using an Ant script that will create a copy of the WAR artifact with some files changed depending on the environment I chose. This adapts for things like JDBC connection strings, properties files, etc. that are different in each environment.
I understand Maven can use profiles, as explained in this answer. However, I'm stuck on figuring out how to make a secondary WAR file for the environment. e.g. I start with "myproject.war" created from the build step, and I want to create "myproject-dev.war", then deploy it to the dev Tomcat server. I figure I can use the antrun maven plugin to make the file changes, but I don't know how to hook it into the lifecycle. Then, I'd need to use the tomcat plugin to deploy.
Any suggestions on how this could be configured?
Let us assume you have a structure like the following (just as an example)
.
|-- pom.xml
`-- src
|-- main
| |-- java
| |-- resources
| |-- environment
| | |-- test
| | | `-- database.properties
| | |-- qa
| | | `-- database.properties
| | `-- production
| | `-- database.properties
| `-- webapp
You can define a assembly descriptor 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>
Furthermore you need a maven-assembly-plugin configuration like the following:
<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>
</executions>
</project>
If you add a separate assembly-descriptor for each environment and add a line with the descriptor you can create with a single call the packages for each environment.
One drawback of this you have several assembly-descriptors which are aside from a few lines identical.
So going more you can use the iterator-maven-plugin to reduce the configuration and mainenance hassle like this:
<plugin>
<groupId>com.soebes.maven.plugins</groupId>
<artifactId>iterator-maven-plugin</artifactId>
<version>0.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>iterator</goal>
</goals>
<configuration>
<items>
<item>test</item>
<item>prod</item>
<item>dev</item>
</items>
<pluginExecutors>
<pluginExecutor>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
</plugin>
<goal>single</goal>
<configuration>
<descriptors>
<descriptor>src/assembly/iterator.xml</descriptor>
</descriptors>
</configuration>
</pluginExecutor>
</pluginExecutors>
</configuration>
</execution>
</executions>
</plugin>
So furthermore you need an appropriate assembly descriptor 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>${item}</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/${item}/</directory>
<includes>
<include>**</include>
</includes>
</fileSet>
<fileSet>
<outputDirectory>WEB-INF</outputDirectory>
<directory>${project.build.directory}/environment/${item}/</directory>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
This makes it simple and convenient to maintain such a build. A full working example can looked at the integration tests of iterator-maven-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>

Categories

Resources