Build a site zip with Maven - maven

actually, I generate a maven site containing the documentation of my project. It works very well, in fact if works so well that my customers wants to get that site as a deliverable (for obvious documentation purpose).
How can I tell Maven to build a zip of the whole site and deploy it to my artifacts manager (Nexus)? I've tried several things, but if I understand correctly, deploying artifacts and generating the site are using different livecycle, and the site generation occurs after the deployment of the artifacts..
I could obviously get the generated site from the location it's deployed during site-deploy, but I would greatly appreciate an automatic and centralized way...
PS: giving access to the customer to our internal site is NOT an option.

Here is a working solution delegated to a Maven profile to isolate the behavior (and speed-up normal builds), but which could also be integrated in the default build if required (although not recommended).
<profiles>
<profile>
<id>site-zip</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.4</version>
<executions>
<execution>
<id>pack-site</id>
<phase>prepare-package</phase>
<goals>
<goal>site</goal>
<goal>jar</goal>
</goals>
<configuration>
<attach>false</attach>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.coderplus.maven.plugins</groupId>
<artifactId>copy-rename-maven-plugin</artifactId>
<version>1.0.1</version>
<executions>
<execution>
<id>rename-file</id>
<phase>prepare-package</phase>
<goals>
<goal>rename</goal>
</goals>
<configuration>
<sourceFile>${project.build.directory}/${project.build.finalName}-site.jar</sourceFile>
<destinationFile>${project.build.directory}/${project.build.finalName}-site.zip</destinationFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<goals>
<goal>attach-artifact</goal>
</goals>
<phase>package</phase>
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.build.finalName}-site.zip</file>
<type>zip</type>
<classifier>site</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
What the profile is actually doing:
Configuring an execution of the Maven Site Plugin, attached to the prepare-package phase and running the site and jar goals (as also suggested by #khmarbaise).
Renaming the file from jar to zip via the Copy Rename Maven Plugin
Attaching the zip to the build via the Build Helper Maven Plugin and its attach-artifact goal
As such, running
mvn clean install -Psite-zip
Will also install in your local Maven cache the zipped site. The deploy phase would do the same on your target Maven repository then.
Note that the Maven Site Plugin and the Copy Plugin must be declared in the order above to follow the required flow within the same phase.
Also note that if zip is not a strong requirement, you can then just skip the Copy and Build Helper executions and only use the Maven Site execution. By default the jar created providing the site is already attached to the build (and hence it will be installed and deployed automatically). In order to have the zip, we had to disable this behavior (<attach>false</attach>) and re-attach it via the Build Helper plugin.
The generated zipped has automatically a classifier, which is site in this case.

You can use the maven-site-plugin.

Related

Preventing Maven Modules from being Deployed

I followed this tutorial to created a Maven build that can publish artifacts to Maven Central.
It works, and most of the tutorial is for authentication of some sort, so the only relevant part of it might just be:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<executions>
<execution>
<id>default-deploy</id>
<phase>deploy</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
Now I wanted to only deploy two of the seven modules in total, so I added this to the parent POM:
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
And <skip>false</skip> to the two modules I actually want to deploy.
This doesn't work. All modules get deployed.
I checked the effective POM, and it clearly shows skip=false for the two modules I want to deploy and skip=true for the other five modules.
Since deploying to Maven Central isn't really a reversible process, I don't want to trial and error my way through this problem, hence the question: How do I prevent Maven modules from deploying to Maven Central?
If you are deploying to Maven Central, it is the Nexus Staging Plugin that is doing the deployment instead of the Deploy plugin, so the configuration of the deploy plugin has no effect. To make the Nexus deploy plugin skip, set skipNexusStagingDeployMojo in its configuration to true.
For a complete example, you can look at one of my projects I deployed to Maven Central with the same problem - I want to deploy everything except the integration test modules.
In the parent POM, the Nexus deploy plugin is defined like normal as described in the tutorial (https://bitbucket.org/prunge/shoelaces/src/2347535282c9f5bb58d33cca22d9dd65c9db2c2b/pom.xml#pom.xml-200):
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.8</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
and in the integration tests project (which itself has children that inherit this configuration) the staging plugin is skipped (https://bitbucket.org/prunge/shoelaces/src/2347535282c9f5bb58d33cca22d9dd65c9db2c2b/integration-tests/pom.xml#pom.xml-28):
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<skipNexusStagingDeployMojo>true</skipNexusStagingDeployMojo>
</configuration>
</plugin>
This results in everything by default being deployed to Central except the integration tests project and everything underneath that.

Copy dependencies AND plugins with Maven

As our customer wants to build the project at his environment we have to deliver (beside the sources) our dependencies and our used plugins both not available from MavenCentral.
How can I copy the used plugins (including their dependencies but without referring each) in a way like the dependencies plugin is doing it for "normal" libs?
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-acme-dependencies</id>
<phase>verify</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<addParentPoms>true</addParentPoms>
<copyPom>true</copyPom>
<useRepositoryLayout>true</useRepositoryLayout>
<overWriteReleases>true</overWriteReleases>
<includeGroupIds>org.acme</includeGroupIds>
<excludeGroupIds>${project.groupId}</excludeGroupIds>
<outputDirectory>${project.build.directory}/dependencies</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
The most reliable way would be to build your project against an empty Maven local repository and copy/enumerate the artifacts that find there afterwards.
Unfortunately, I never found a Maven plugin that lists you "everything you need to build a given project".

IOException thrown when processing xsd dependencies in maven

I have a problem while processing .xsd file during my maven build.
I use jaxb2 plugin but I have to download external dependiencies from my .xsd files. The problem is that these dependencies (.xsd) are from enviroment which is unstable and very often my build fails because maven cannot download xsd file. How to configure jaxb plugin to force him to try download xsd few times to prevent build failure?
Part of my pom.xml configuration:
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<configuration>
<strict>false</strict>
<extension>true</extension>
<args>
<arg>-Xfluent-api</arg>
<arg>-XtoString</arg>
<arg>-Xsetters</arg>
<arg>-XenumValue</arg>
</args>
<plugins>
<plugin>
<groupId>net.java.dev.jaxb2-commons</groupId>
<artifactId>jaxb-fluent-api</artifactId>
<version>${jaxb.fluentapi.version}</version>
</plugin>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>0.9.3</version>
</plugin>
</plugins>
<bindingDirectory>src/main/resources/jaxb</bindingDirectory>
<bindingIncludes>
<include>bindings.xml</include>
</bindingIncludes>
<schemas>
<schema>
<fileset>
<!-- Defaults to schemaDirectory. -->
<directory>${project.basedir}/src/main/resources/orbeons</directory>
<!-- Defaults to schemaIncludes. -->
<includes>
<include>*.xsd</include>
</includes>
</fileset>
</schema>
</schemas>
</configuration>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.basedir}/generated-sources/orbeons</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Author of the maven-jaxb2-plugin here.
You have two parts here: managing the downloads of external resources and compiling the schemas, rewriting "external" links to local files.
The first (managing downloads) is not in the scope of the maven-jaxb2-plugin, the second is supported with
catalogs.
In short, you can create a catalog file like this:
REWRITE_SYSTEM "http://www.w3.org" "w3c"
Or this:
REWRITE_SYSTEM "http://schemas.opengis.net" "maven:org.jvnet.ogc:ogc-schemas:jar::!/ogc"
And use this file to "rewrite" absolute links to local files or resources within Maven artifacts:
<configuration>
<catalog>src/main/resources/catalog.cat</catalog>
</configuration>
As for the first part, I don't think managing downloads with retries, continuations and all other stuff should be in the scope of the JAXB2 Maven plugin.
ps. You don't need build-helper-maven-plugin/add-source with maven-jaxb2-plugin, source directory is added automatically.
Apparently the maven-jaxb2-plugin does not support such a feature. (And neither does the maven-download-plugin nor even the maven-dependency-plugin).
Three solutions come into my mind at the moment (plus two and a half inspired by LIttle Ancient Forest Kami's comment) [Numbers reflect the precedence of what I would do]:
Use a CI tool (Jenkins, etc.) that supports retry on job failure. [1]
Handmade:
Use the GMavenPlus plugin with a script ... [2]
Use the Maven AntRun plugin with a script ... [3]
Use the Exec Maven plugin with a program ... [5]
... that performs the download and retry and bind it to the generate-resources phase in your project's POM.
Create a Maven plugin with appropriate parameters (url, outputDirectory, retryCount) that uses the maven-download-plugin and performs the retry. Bind its goal to the generate-resources phase in your project's POM. [4]
Create a check-download Maven project that uses the maven-download-plugin bound to the generate-resources phase to download the .xsd. [6]
Create a shell script that contains the following (in pseudo code):
download:
counter++
<check-download project>/mvn generate-resources
if error and counter < maxRetryCount goto download
if not error
<your project>/mvn ...
else
display appropriate error message
There is also a question Maven download retry? from 2005. Unanswered.

Unpack an EAR file using maven

I have an EAR file from some build. I want to extract the contents of this EAR file into another folder. I am confused how to do this. I have looked and tried
http://maven.apache.org/plugins/maven-ear-plugin/
and
http://maven.apache.org/plugins/maven-dependency-plugin/usage.html
but either maven is unable to find the file or it has dependency issues.
Since I am new to maven I don not understand how to set these plugins up.
I got the following error on using the below plugin.
Failure to find ECM:ECM:ear:1.0 in http://repo.maven.apache.org/maven2 was cached in the local repository
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>ECM</groupId>
<artifactId>ECM</artifactId>
<version>1.0</version>
<type>ear</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/earoutput</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
You can do it using dependency:unpack-dependencies. I just modify my answer because according to your comments, your ear is generated by some other build. If you do not have an Enterprise repository that you can deploy your ear artifact, you have to use "system" scope, but please note that it is usually discouraged.
Add below dependency to your pom.xml
<dependency>
<groupId>ECM</groupId>
<artifactId>ECM</artifactId>
<version>1.0</version>
<type>ear</type>
<scope>system</scope>
<systemPath>/path/to/your/abc.ear</systemPath>
</dependency>
Add the below plugin to your postBuild module pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeArtifactIds>ECM</includeArtifactIds>
<outputDirectory>${project.build.directory}/earoutput</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Have you looked at this example of Maven EAR plugin for Unpacking a module yet?
The Maven Dependency Plugin and its unpack goal can do this.
Sample configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>myear</groupId>
<artifactId>myear</artifactId>
<version>1.0</version>
<type>ear</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/earoutput</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
This takes the 'myear.ear' artifact and extracts it to the 'target/earoutput' directory. This also works with JARs, WARs and any other zip-like file. The phase this executes under is 'package' - this may be too late if you need to use these resources in other parts of the build. Change the phase to something earlier such as 'generate-resources' if needed.
You mentioned that you already tried using the dependency plugin. Is the EAR file from another Maven project, and has it been installed in the local Maven repository? If it still doesn't work post the plugin configuration you tried to use.
(edit: update information on dependencies and local repository)
For this to work, your EAR file needs to be put into your local Maven repository (this is just a directory on your disk). But if other people need to build your project as well, you have a few options:
import the EAR into your local repository, and also deploy to a remote repository so everyone can get it (recommended, but requires you to set up a corporate Maven repository)
give the EAR to everyone and have them put it into their local repository using a couple of Maven commands (might be OK for a few developers, less overhead than setting up a whole repository server)
check the dependent EAR into source control under your project and unpack it (not the recommended way of doing things) in a goal in your project
Importing into your local repository is easy. It's very similar to these instructions.
Use the following command:
mvn install:install-file -Dfile=<path-to-EAR-file-on-local-filesystem> -DgroupId=myear
-DartifactId=myear -Dversion=1.0 -Dpackaging=ear
(modify path, groupId, artifactId and version as needed)
Group ID and artifact ID are there simply to uniquely identify artifacts.
Once you install this in the local repository, the dependency plugin should work and find the artifact.

Configuring Javadoc aggregation in Maven

I'm trying to create an aggregate Javadoc site for all the modules in my project, but I can't seem to configure the plugin in a way that is satisfactory. Mainly, I can't seem to get it to aggregate the javadocs all the while detecting links and excluding certain packages. Essentially, it appears the configuration of the plugin is ignored entirely.
I have a root pom.xml that refers to a bunch of submodules and contains the following configuration:
<modules>
<module>foo</module>
<module>bar</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.maven.apache.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<executions>
<execution>
<id>aggregate</id>
<phase>site</phase>
<goals>
<goal>aggregate</goal>
</goals>
<configuration>
<links>
<link>http://docs.oracle.com/javase/6/docs/api</link>
<link>http://static.netty.io/3.5/api</link>
<link>http://google-guice.googlecode.com/git/javadoc</link>
<link>http://docs.guava-libraries.googlecode.com/git-history/release/javadoc</link>
<link>http://fasterxml.github.com/jackson-databind/javadoc/2.0.4</link>
<link>https://developers.google.com/protocol-buffers/docs/reference/java</link>
</links>
<bootclasspath>${sun.boot.class.path}</bootclasspath>
<additionalJOption>-J-Xmx1024m</additionalJOption>
<detectJavaApiLink>true</detectJavaApiLink>
<detectLinks>true</detectLinks>
<excludePackageNames>*.testing.*</excludePackageNames>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
But when I run mvn javadoc:aggregate with this setup, I end up with a javadoc site that has no links to any of the referenced libraries and still includes all the testing classes.
I don't even see the plugin attempting to download the package-list for each declared link source.
On the other hand, generating the javadoc for each individual module works well and as expected.
What am I getting wrong?
Plugin configurations can be placed on two levels; inside the execution tag or outside of it ("global").
When the configuration is inside the execution tag it belongs to that particular execution. In your case you will have to run mvn site for it to execute since it is bound to that phase.
When the mvn javadoc:aggregate command is used it looks for the "global" configuration. In your pom there is no such configuration and thus it uses the default configuration.
Change your plugin configuration to this instead:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration>
<links>
<link>http://docs.oracle.com/javase/7/docs/api</link>
<link>http://static.netty.io/3.5/api</link>
<link>http://google-guice.googlecode.com/git/javadoc</link>
<link>http://docs.guava-libraries.googlecode.com/git-history/release/javadoc</link>
<link>http://fasterxml.github.com/jackson-databind/javadoc/2.0.4</link>
<link>https://developers.google.com/protocol-buffers/docs/reference/java</link>
</links>
<bootclasspath>${sun.boot.class.path}</bootclasspath>
<additionalJOption>-J-Xmx1024m</additionalJOption>
<detectJavaApiLink>true</detectJavaApiLink>
<detectLinks>true</detectLinks>
<excludePackageNames>*.testing.*</excludePackageNames>
</configuration>
<executions>
<execution>
<id>aggregate</id>
<phase>site</phase>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
You can place a configuration inside the execution part to override and specialize the configuration for that execution.
BTW The <groupId> is wrong in your pom. It should be
<groupId>org.apache.maven.plugins</groupId>
and not
<groupId>org.maven.apache.plugins</groupId>

Resources