Include parents documentation into zip-file - java

I have a multimodule maven project and I want to create an ZIP-File in the end which contains an .ear and the documentation.
The documentation is made with docbkx and is part of the parent.
The .ear file is made in a module.
My structure:
partent
|-src/docbkx
|-moduleEJB
|-moduleEAR
Where I am now?
I can create an ZIP including my ear (using mvn clean package)
I can create the PDF output of my documentation (using mvn clean site)
I want now to include the generated PDF of my documentation into my ZIP-file. How can I achieve that? I tried to include the target directory of my parent project but nothing happened - which seems logical because when I run mvn clean package the documentation PDF isn't made as it's part of the pre-sitelifecycle.
This is my assembly.xml
<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>bin</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}</directory>
<includes>
<include>*.ear</include>
</includes>
<outputDirectory>/</outputDirectory>
</fileSet>
<fileSet>
<directory>${parent.project.build.directory}/docbkx/pdf</directory>
<includes>
<include>*.pdf</include>
</includes>
<outputDirectory>docs/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
This is the part of docbooks execution of my parent.pom:
<executions>
<execution>
<phase>pre-site</phase>
<goals>
<goal>generate-pdf</goal>
</goals>
<configuration>
</configuration>
</execution>
</executions>
Thanks in advance
edit: I also tried to change the phase of docbkx to compile but still nothing in my final zip.

I got it myself. As the parent project is the last to build I created a new project named documentation to create the PDF. I then added this to the zip using a fileset
<fileSet>
<directory>${project.build.directory}/../../documentation/target/docbkx/pdf</directory>
<includes>
<include>*.pdf</include>
</includes>
<outputDirectory>docs/</outputDirectory>
</fileSet>

Related

How can I add regular folder to my repository using a Maven build?

Right now if I run my project as a "Maven install", my Java Maven build creates a war file and a zip file, both under the same directory location.
How can I have this build add a regular folder to this directory location, and put the zip file inside that folder?
More Info
I tried using the maven-assembly-plugin. In repository.xml, I specify which files to put in my zip. The files are in ${project.basedir}/files. I tried putting the files inside an "extrafolder" so they're at ${project.basedir}/files/extrafolder, hoping this extra folder would be in my local repository, but Maven ignored the folder and still put both the war and zip in the same repository.
Here's the plugin in my POM:
<project>
[...]
<build>
[...]
<plugins>
[...]
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<descriptors>
<descriptor>src/assembly/repository.xml</descriptor>
</descriptors>
</configuration>
</plugin>
[...]
</project>
And here's the repository.xml file:
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
<id>repository</id>
<formats>
<format>tar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}/files</directory>
<outputDirectory>/</outputDirectory>
<filtered>true</filtered>
<includes>
<include>**/*.*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
You should configure the outputDirectory as extrafolder if you need it. Example as below:
<fileSets>
<fileSet>
<directory>${project.basedir}/files</directory>
<outputDirectory>extrafolder</outputDirectory>
<filtered>true</filtered>
<includes>
<include>**/*.*</include>
</includes>
</fileSet>
</fileSets>
To configure the plugin to put the zip file into a specific folder as below:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<outputDirectory>extrafolder</outputDirectory>
<descriptors>
<descriptor>src/assembly/repository.xml</descriptor>
</descriptors>
</configuration>
</plugin>
Find more details here: https://maven.apache.org/plugins/maven-assembly-plugin/single-mojo.html#outputDirectory

Whats the best way to bundle the whole project in Maven?

I'd like to create a fat-jar which is autoexecutable (Shade Plugin), but also includes sources, resources, tests, and everything in a Eclipse-importable way.
The jar would be single-file executable app, which also contains the whole project in an importable fashion as a maven project someway (after unzipping the jar, I assume).
Another option would be a resulting project zip that includes the binary distribution at base level.
Is there such a thing?
A possible solution requires 3 steps:
Create an uber-jar of the project with the maven-shade-plugin. This JAR will contain all the dependencies and will be executable.
Create a side artifact consisting of the sources of the project with the maven-assembly-plugin. This ZIP will contain the pom.xml and all of the sources under src.
Create another side artitact that will effectively be our final artifact, that will contain both the unpacked shaded JAR (to make it effectively executable) and the sources ZIP.
This would be a possible configuration:
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>make-uberjar</id>
<goals>
<goal>shade</goal>
</goals>
<phase>package</phase>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>fully.classified.name.to.main.Class</mainClass>
</transformer>
</transformers>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>sources</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly-sources.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>final</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
This configures the execution of the maven-shade-plugin and 2 execution of the maven-assembly-plugin. The first execution will creates the sources ZIP. This would be the assembly-sources.xml assembly descriptor file:
<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>sources</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<includes>
<include>pom.xml</include>
<include>src/**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
It includes pom.xml and everything under src into a ZIP having the sources classifier.
The second assembly.xml assembly descriptor file would be:
<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-sources</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<includes>
<include>${project.groupId}:${project.artifactId}:jar:${project.version}</include>
</includes>
<unpack>true</unpack>
</dependencySet>
<dependencySet>
<useProjectAttachments>true</useProjectAttachments>
<includes>
<include>${project.groupId}:${project.artifactId}:zip:sources:${project.version}</include>
</includes>
</dependencySet>
</dependencySets>
</assembly>
This creates 2 <dependencySet>. The first one unpacks the shaded JAR (which replaced the main artifact at that point in the build). The second one simply includes the sources ZIP attached artifact; note that we need to use <useProjectAttachments> to include the attached sources ZIP.
When you run mvn clean install, you will have as result a file {finalName}-jar-with-sources.jar that will be your wanted executable JAR. It will also contain a ZIP file of all the sources in the root folder.
I found that using the maven assembly-plugin gives you the best control over these kind of things, for both an uber jar or an installable zip. The shade plugin works well for uber jars, but not so well for installer zips or installers.
In the past i also augmented that functionality by adding in the mix the izpack plugin, which creates a real installer, off of the distributable zip that you create with the assembly plugin.
For example, with the assembly-plugin you can choose to include or exclude certain file resources. This happens for example when you want to use a configuration file while working with the IDE, but you really want to exclude it in the final distribution zip, or you want to include a slightly different one.
Same happens when you want to generate an rpm: the assembly plugin can help quite a bit in first preparing what's needed for the rpm plugin to operate.
The assembly plugin comes with all sort of settings, which you declare in its xml configuration file and it is well documented.
In most cases, trying to pack all the application dependencies in a single .jar is a bad idea, mainly because .jars are not designed to be used this way. In fact, they might contain META-INF/ and other jar-specific files that might clash each other.
When I have to build binary distributions that can be run from the command line, I use the Assembly plug-in, as I've described in this post. If you need to distribute a GUI application or a one-click, self-contained web server, the approach would be very similar.

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

Include a file multiple times with different names in a Maven-built JAR

I work with Java resource bundles that are included in the final JAR using Maven's resource tag:
<resources>
<resource>
<targetPath>lang/</targetPath>
<filtering>true</filtering>
<directory>${basedir}/src/main/resources/</directory>
<includes>
<include>localization*.properties</include>
</includes>
</resource>
</resources>
Due to the nature of the automatic resource loading, I need to include the English file two times: As the standard English file (localization_en.properties) and as the base file that provides a fallback if a more specific localization is not found (localization.properties). At the moment, both of these files are present in the resource directory, even through their content is exactly the same.
I am looking for a way that lets Maven duplicate the present localization_en.properties and include it with the base name, so I do not need two separated files in the resource directory any more.
I believe that you can do what you need using the ant copy task. Something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>copy-files</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target name="copy your files">
<copy file="a.txt" tofile="a_eng.txt" />
<copy file="a.txt" tofile="a.txt" />
</target>
</configuration>
</execution>
</executions>
</plugin>
You can use the Maven assembly plugin to achieve this. Essentially you build a JAR from scratch, using the classes in your target directory (which will already include your normal copied resources), then add a copy of your specific resource with a new name.
Note, to exactly match what you would normally get in a build, you have to manually copy the pom.properties and pom.xml into the resulting JAR. Perhaps a passing commenter will know a way to do this automatically?
<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>example</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<!-- Copy all compiled classes and normal copied resources -->
<fileSets>
<fileSet>
<directory>${project.build.outputDirectory}</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
<files>
<!-- Specifically add renamed file -->
<file>
<source>${basedir}/src/main/resources/example.txt</source>
<destName>example.txt2</destName>
<outputDirectory>/</outputDirectory>
</file>
<!-- Copy files normally included in JAR -->
<file>
<source>${project.build.directory}/maven-archiver/pom.properties</source>
<outputDirectory>META-INF/maven/${project.groupId}/${project.artifactId}</outputDirectory>
</file>
<file>
<source>${basedir}/pom.xml</source>
<outputDirectory>META-INF/maven/${project.groupId}/${project.artifactId}</outputDirectory>
</file>
</files>
</assembly>
Note: if you intend to create a jar-with-dependencies style output (i.e. with all dependencies auto-included), there is a much neater way to achieve the same goal:
<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>example</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<!-- Make executable JAR -->
<dependencySets>
<dependencySet>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
</dependencySet>
</dependencySets>
<files>
<!-- Specifically add renamed file -->
<file>
<source>${basedir}/src/main/resources/example.txt</source>
<destName>example.txt2</destName>
<outputDirectory>/</outputDirectory>
</file>
</files>
</assembly>

Normalize remote Maven repo JAR filename?

I'm building a web app with Dropwizard, and trying to use the Shiro bundle module (Maven repo) to integrate Shiro authentication.
My problem is that in the remote Maven repo the filename is dw-shiro-bundle-0.0.1-20130412.232035-4.jar, instead of dw-shiro-bundle-0.0.1-SNAPSHOT.jar. I understand this happens when you build the same SNAPSHOT version four times to avoid clobbering the first three, and the index takes care of finding the latest one.
However I'm also following this advice to avoid using maven-shade-plugin and effectively do the shading myself, since the final JAR is otherwise too big. maven-assembly-plugin is configured to copy the Shiro bundle JAR to lib/dw-shiro-bundle-0.0.1-SNAPSHOT.jar, but in the final JAR's MANIFEST.MF, the dependency is listed as io.ifar.dw-shiro-bundle-0.0.1-20130412.232035-4.jar, and hence I get a ClassDefNotFoundError at runtime.
A workaround is to manually rename the lib jar to io.ifar.dw-shiro-bundle-0.0.1-20130412.232035-4.jar so it gets picked up on the classpath, but it's not really a solution. Is there a way to either:
fix the MANIFEST.MF entry
normalize the name of third-party JARs as they are downloaded by Maven to strip any build numbers, or
automate the process of renaming the JAR file to include the build number?
My plugins are as follows:
In maven-jar-plugin:
<configuration>
<forceCreation>true</forceCreation>
<archive>
<manifest>
<mainClass>${mainClass}</mainClass>
<addClasspath>true</addClasspath>
<classpathLayoutType>custom</classpathLayoutType>
<customClasspathLayout>lib/${artifact.groupId}.${artifact.artifactId}-${artifact.version}${dashClassifier?}.${artifact.extension}</customClasspathLayout>
</manifest>
</archive>
</configuration>
In maven-dependency-plugin:
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<prependGroupId>true</prependGroupId>
</configuration>
</execution>
</executions>
assembly.xml:
<?xml version="1.0" encoding="UTF-8"?>
<assembly>
<id>package</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>true</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>target/dependency</directory>
<outputDirectory>/lib</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<includes>
<include>configuration.yml</include>
</includes>
</fileSet>
</fileSets>
</assembly>
As soon as I posted this I found the answer. I guess that's just how it goes.
Buried in the documentation for the Maven Archiver is a section on Handling Snapshot Versions, which says to replace ${artifact.version} with ${artifact.baseVersion}. And it works! The 20130412.232035-4 on the end is replaced with SNAPSHOT.

Categories

Resources