Maven assembly plugin: excluding files while using a standard descriptorRef - maven-2

I'm developing a simple, stand-alone, command line Java application. The project is managed by Maven. I'd like to build a deliverable, which can be copied and run on the client's machine.
The maven-assembly plugin with the default 'jar-with-dependencies' type is ok for me, but
I don't want to package the log4j.properties file into the jar. I'd rather have it in a separate "res" folder.
I've managed to put a Class-Path header in the manifest file for the res folder, but I'm having trouble excluding the log4j.properties file from the generated jar.
What I'm trying is to have the file excluded without writing a custom assembly descriptor. I'd like to customize the default solution, like this:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/log4j.properties</exclude>
</excludes>
<archive>
<manifest>
<mainClass>com.my.App</mainClass>
</manifest>
<manifestEntries>
<Class-Path>res/</Class-Path>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration></plugin>
but it doesn't work. Do I have to write a custom assembly descriptor for this?

From the doc, it looks like you cannot exclude files by customizing <plugin> parameters alone.
<excludes> does not look like a valid parameter for the plugin and is thus getting ignored.

Related

Intellij path rule to automatically recognize generated sources folder

I would like to know if it is possible to set up a rule that marks a generated sources folder as generated sources root in Intellij Idea automatically.
Usually, Intellij detects the target/generated-sources directory as generated sources. My problem is that I also need it to automatically recognize the directory target/generated as generated sources, which Intellij never did in my case.
This is because of a maven plugin that I use for generating code from XSD schema:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-xjc-plugin</artifactId>
<version>${cxf.version}</version>
<configuration>
<extensions>
<extension>org.apache.cxf.xjcplugins:cxf-xjc-dv:${cxf.version}</extension>
</extensions>
</configuration>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>xsdtojava</goal>
</goals>
<configuration>
<xsdOptions>
<xsdOption>
<xsd>src/main/resources/schema.xsd</xsd>
<packagename>org.example.project.common.request</packagename>
</xsdOption>
</xsdOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
For some reason, this plugin generates code into the target/generated directory, and not into the target/generates-sources, of which I read that it is the convention and the default from many points of view.
I've tried searching on the web with similar keywords like in the title, but this was the closest solution to what I wanted to achieve. And even this solution doesn't solve my problem because Intellij doesn't allow setting some path patterns; it only offers a few options that don't include target/generated directory.
Another solution suggests changing the target output, which I can't do in every single project I work on; that is not a solution either.
This is important to me because I work with many projects, and sometimes when my code builds with maven but doesn't compile with Intellij I forget to check whether I marked all the generated folders as sources, or I don't even know there are generated sources in the project.
Does someone know a way I can achieve that Intellij automatically detects source files in target/generated directory?

Maven Assembly Plugin is not setting the MainClass manifest setting

I have a maven project which generates a jar via the maven assembly plugin I want to run as a console app. However, the MainClass attribute is not being set in MANIFEST.MF. Here is my plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>net.justaprogrammer.poi.cleanser.Cleanser</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
However, this does not get added to the MANIFEST.MF in the jar generated by mvn package. The manifest generated is below:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: zippy
Build-Jdk: 1.6.0_25
What am I doing wrong?
I missed that you weren't generating your assembly on package. You have a jar project, so Maven will build a jar using the maven-jar-plugin. You don't have to have anything in your pom to tell it that. That's Maven's convention-over-configuration working for you. The jar it builds will have only your project classes and resources in it. If you want to add a Main-Class to the manifest in that jar, you should configure the jar plugin to do so. Basically, just move that archive configuration to the jar plugin.
However, if you actually want to assemble an executable fat jar--that is, a jar that includes all of your classes as well as the classes of all of your dependencies--then you have the setting in the right place, but you need to actually run the assembly plugin either using mvn assembly:single or by binding that goal to a lifecycle phase. To be clear, if you do this, then your project will output two jars: one that contains your project files and one that contains that plus the contents of all the libraries that your project depends on. The former is built by the jar plugin. That latter is built by the assembly plugin. Note that fat jars aren't commonly used, and you can run into unusual problems when you use them because they're rather outside the realm of normal Java stuff.
For copy&paste fans like me, assembled from above answer, and http://maven.apache.org/plugins/maven-assembly-plugin/usage.html#Execution:_Building_an_Assembly:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.db.search.filenet.Load</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
If you happen to be using the maven shade plugin to build a fat jar (rather than or in addition to using the assembly plugin), it's worth noting that the shade plugin handles entires in the MANIFEST.MF file a bit differently; see the shade plugin's executable jar page.
You probably need to add the maven-jar-plugin configuration too and configure the MainClass there also. The assembly unpacks all JAR files (e.g. project jar and dependency jars) and I think that the last MANIFEST.MF found in the list of JAR files "overwrites" the expected/generated manifest.mf.

How can I merge resource files in a Maven assembly?

I'm using Maven and its assembly plugin to build a distribution package of my project like this:
one project assembles a basic runtime (based on Felix), with the appropriate directories and bundles, in a ZIP file.
third-party libraries are collected in one project each and either converted to OSGi bundles or, if they are already OSGi compatible, they are just copied
my own project consists of several modules that are built into OSGi bundles, too.
Now, I'm adding another project that unpacks the ZIP, drops all the other JARs into the proper directories, and repackages it for distribution. Now, my bundles might contain configuration files that I want to merge into, rather than replacing, identically named ones in the runtime assembly. How do I do that?
The files are plain text (property files), but I might run into a similar situation with XML files later.
Expanding a bit on Juergen's answer for those who stumble on this - the containerDescriptorHandler in the descriptor can take four values (v2.3), these are metaInf-services, file-aggregator, plexus, metaInf-spring. It's a bit buried in the code (found in the package org.apache.maven.plugin.assembly.filter) but it is possible to aggregate config/properties files.
Here's an example descriptor that aggregates the META-INF/services and
named property files located in com.mycompany.actions.
descriptor.xml
<assembly>
...
<containerDescriptorHandlers>
<containerDescriptorHandler>
<handlerName>metaInf-services</handlerName>
</containerDescriptorHandler>
<containerDescriptorHandler>
<handlerName>file-aggregator</handlerName>
<configuration>
<filePattern>com/mycompany/actions/action.properties</filePattern>
<outputPath>com/mycompany/actions/action.properties</outputPath>
</configuration>
</containerDescriptorHandler>
</containerDescriptorHandlers>
....
</assembly>
The file-aggregator can contain a regular expression in the filePattern to match multiple files. The following would match all files names 'action.properties'.
<filePattern>.+/action.properties</filePattern>
The metaInf-services and metaInf-spring are used for aggregating SPI and spring config files respectively whilst the plexus handler will aggregate META-INF/plexus/components.xml together.
If you need something more specialised you can add your own configuration handler by implementing ContainerDescriptorHandler and defining the component in META-INF/plexus/components.xml. You can do this by creating an upstream project which has a dependency on maven-assembly-plugin and contains your custom handler. It might be possible to do this in the same project you're assembling but I didn't try that. Implementations of the handlers can be found in org.apache.maven.plugin.assembly.filter.* package of the assembly source code.
CustomHandler.java
package com.mycompany;
import org.apache.maven.plugin.assembly.filter.ContainerDescriptorHandler;
public class CustomHandler implements ContainerDescriptorHandler {
// body not shown
}
then define the component in /src/main/resources/META-INF/plexus/components.xml
components.xml
<?xml version='1.0' encoding='UTF-8'?>
<component-set>
<components>
<component>
<role>org.apache.maven.plugin.assembly.filter.ContainerDescriptorHandler</role>
<role-hint>custom-handler</role-hint>
<implementation>com.mycompany.CustomHandler</implementation>
<instantiation-strategy>per-lookup</instantiation-strategy>
</component>
</components>
</component-set>
Finally you add this as a dependency on the assembly plugin in the project you wish to assemble
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptors>
<descriptor>...</descriptor>
</descriptors>
</configuration>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>sample-handler</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</plugin>
and define the handlerName in the descriptor
descriptor.xml
...
<containerDescriptorHandler>
<handlerName>custom-handler</handlerName>
</containerDescriptorHandler>
...
The maven-shade-plugin can also create 'uber-jars' and has some resource transforms for handling XML, licences and manifests.
J
Old question but stumbled over it while trying to solve similar problem: Assembly plugin 2.2 has capabilities to merge files: http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html#class_containerDescriptorHandler
e.g. handlerName "metaInf-services" (will concat all META-INF/services files), "metaInf-spring" are the only ones I know of (I personally needed metaInf-services)
I don't know of a robust solution to this problem. But a bit of looking around shows that somebody has created a plugin to merge properties files. By the look of it you need to tell it which files to merge, which is a good thing as you don't want this applied willy nilly.
Assuming you have used dependency-unpack to unpack the zip to a known location, it would be a case of configuring the plugin to merge each pair of properties files and specify the appropriate target location.
You could extend the plugin to handle XML by using something like xmlmerge from EL4J, as described in this Javaworld article.
Ive also created a merge files plugin, in my case i use it to merge SQL files from various projects into a single installer SQL file which can create all the schemas/tables/static data etc for our apps in a single file, http://croche.googlecode.com/svn/docs/maven-merge-files-plugin/0.1/usage.html
https://github.com/rob19780114/merge-maven-plugin (available on maven central) also seems to do the job.
See below for an example configuration
<plugin>
<groupId>org.zcore.maven</groupId>
<artifactId>merge-maven-plugin</artifactId>
<version>0.0.3</version>
<executions>
<execution>
<id>merge</id>
<phase>generate-resources</phase>
<goals>
<goal>merge</goal>
</goals>
<configuration>
<mergers>
<merger>
<target>${build.outputDirectory}/output-file-1</target>
<sources>
<source>src/main/resources/file1</source>
<source>src/main/resources/file2</source>
</sources>
</merger>
<merger>
<target>${build.outputDirectory}/output-file-2</target>
<sources>
<source>src/main/resources/file3</source>
<source>src/main/resources/file4</source>
</sources>
</merger>
</mergers>
</configuration>
</execution>
</executions>

How to exclude pom.xml from Maven generated war?

Using Maven war plugin, I generate WAR which includes following directory:
META-INF
-- maven
-- com.abc.def
-- myServlet
-- pom.xml
-- pom.properties
In release, I want to exclude this maven directory. How can I do that?
I tried latest maven-war-plugin (2.1-beta-1), it has configuration "packagingExcludes", but it doesn't work as I wish.
Any suggestions?
I'm not sure but I think that the Maven Archiver (which is mainly used by plugins to handle packaging) can be configured to achieve this.
About the <addMavenDescriptor> element, the Maven Archiver Reference says:
Whether the generated archive will contain these two Maven files:
The pom file, located in the archive in META-INF/maven/${groupId}/${artifactId}/pom.xml
A pom.properties file, located in the archive in META-INF/maven/${groupId}/${artifactId}/pom.properties
The default value is true.
So a pom configured like this should do the trick:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.0</version>
<configuration>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
Using the standard Maven packaging you can't omit the file to my knowledge. It is possible however to use the maven-assembly-plugin to construct the war, in this case you have much finer grained control over the contents of the artifact, and can omit the pom.xml.
However I have personally found it useful to keep the pom.xml for diagnostic purposes. It can be handy to know what was used to build and assemble the war when trying to figure out what is wrong with your app.
Update: in a bizarre bit of synchronicity to Pascal's answer, I've just been reading up on the Archiver reference and it appears that this can be done by setting the addMavenDescriptor property to false. Personally I would still avoid doing this for reasons given above. But you may want to change your acceptance to Pascal's answer.
Putting a META-INF folder in a resources directory or in the root of your source directory will destroy the META-INF content created by Maven. For WAR files, putting a META-INF in your web content directory will do the same.
Adding other content to that custom META-INF will override what maven would create.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<warSourceExcludes>pom.xml</warSourceExcludes>
</configuration>
</plugin>
or
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<warSourceExcludes>here/there/everywhere/a/pom.xml</warSourceExcludes>
</configuration>
</plugin>

maven javaee application client plugin

I am pretty new to maven.
Is there any plugin or packaging type suitable for building application client jar file ?
I want to add the application-client.xml file to the META-INF folder inside the jar.
The normal jar packaging doesn't include the file.
You should only need to define the project with jar packaging (and as it is the default you don't need to declare it).
If you define the application-client.xml in the src/main/resources/META-INF folder it will be included in the META-INF folder of the final jar.
To define additional information you need to configure the jar plugin as below.
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<configuration>
<archive>
<manifest>
<mainClass>com.mycompany.app.App</mainClass>
<addClasspath>true</addClasspath>
</manifest>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
Check out the guide to working with manifests for full details
I'm not very familiar with the JavaEE support in Maven, but it looks like the ejb plugin can generate a client jar as well if configured properly. Check this page out:
Maven EJB Plugin - Generating an EJB client