Running docker-maven-plugin on the very end of parent pom building - maven

I'm trying to build the docker image containing a group of .jar files built during building parent POM file. What I found till now was the case where the single build of particular module creates separate docker image.
My docker image contains Karaf with the deployed bundles. At some point I achieved the creating docker, but when everything was build. I'm afraid that docker-maven-plugin may not support the case where I want to create docker image from particular folders of bundles (each child project is deploying its bundles to particular folder).
For now I found that parent POM package types supports only three phases, but anyway - all of them are run just as first project during the build. So the question is:
Is it possible to create docker image
containing all bundles built during building the parent POM project which are deployed to one folder
automatically after run some parent POM goal
Below some part of parent POM which finally may not be related to my needs
<build>
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<inherited>false</inherited>
<version>0.4.10</version>
<configuration>
<imageName>test1</imageName>
<dockerDirectory>../karaf-deploy</dockerDirectory>
<resources>
<resource>
<targetPath>../karaf-deploy/</targetPath>
<directory>../karaf-deploy/</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>

Child-parent relationship is simply a special form of dependency, where child depends on parent. As such, parent is always built first, before any children. This also means you cannot build anything in parent that depends on children, because parent depending on a child would be basically a cyclic dependency.
So if you want to bundle just a single artifact, you can add docker plugin to the lifecycle of that single project. But if you want to bundle multiple artifacts, you should follow advice by #khmarbaise:
Define a new separate distribution project (can even be pom packaging or use a special extension)
Add distribution project as child module to existing parent
Add normal Maven dependencies on any artifacts you want to bundle/wrap/include
Define copy-dependencies step for prepare-package phase to copy dependencies to build directory
Define docker-maven-plugin settings for package phase to bundle copied dependencies
Skip step 4 if your distribution plugin can pick dependencies from Maven directly. We're using io.fabric8 docker-maven-plugin where you can define assembly-style descriptor such as this:
<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>all-artifacts</id>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
</assembly>

Related

how to make zip files (produced by a self-made maven plugin)from target folder end up in the local repository?

I am creating my own maven-environment-plugin that creates and bundle resources for a predefined folder structure for each environment defined in the configuration. The plugin is outputting the folder structure and resource in a zip file and placing it in the target folder.
Questions:
How can I make my plugin work like the maven-assembly-plugin so my output to target folder also ends up in my local repository when I use 'mvn install'?
Do I need to mark it or something? Its automaticallly doing it when the maven-assembly-plugin is used.
How does maven-assembly-plugin manage to make sure of this?
I am using mojo for my plugin development.
<plugin>
<groupId>dk.kmd.devops.maven.plugin</groupId>
<artifactId>envconfiguration-maven-plugin</artifactId>
<version>1.0.3</version>
<configuration>
<environments>
<environment>${env.local}</environment>
<environment>${env.dev}</environment>
<environment>${env.t1}</environment>
<environment>${env.t2}</environment>
<environment>${env.p0}</environment>
</environments>
<sourceConfigDir>${basedir}/src/main/config</sourceConfigDir>
<zipEnvironments>true</zipEnvironments>
</configuration>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>generateEnv</goal>
</goals>
</execution>
</executions>
</plugin>
You need to attach (that's the correct terminology in this case) the new artifact (the generated zip file) to the build as part of its official artifacts.
This is basically what the attach-artifact goal of the build-helper-maven-plugin does:
Attach additional artifacts to be installed and deployed.
From its official examples, the attach goal:
Typically run after antrun:run, or another plugin, that produces files that you want to attach to the project for install and deploy.
The another plugin in this case can be the plugin you developed. Hence there are two solutions to your case:
Configure this plugin to attach the generated artifact as a further pom.xml configuration, or
add to your plugin the functionality to automatically attach the generated file
The second case can be covered via Maven API, using the MavenProjectHelper and its attachArtifact method.
In your mojo, you can import is as a component via:
/**
* Maven ProjectHelper
*/
#Component
private MavenProjectHelper projectHelper;
Then use the aforementioned method:
projectHelper.attachArtifact(project, "zip", outputFile);
You should probably already have the required Maven dependency providing it, but just in case it would be this one:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.3.9</version>
</dependency>
Note that the artifact will be attached to the build as an additional artifact via a classifier, that is, a suffix to the default artifact name differentiating it from the default artifact and making it unique as output of the build.
As a reference to real example and to further answer your (last) question, check this query on the GitHub maven-plugins repository, checking for the attachArtifact string, you will see it used in a number of Maven plugins, among which the maven-assembly-plugin, for example here in the AbstractAssemblyMojo class.

How to include a generated file into the war with maven, but to not add it to source

I have a dependencies from other projects (.jsp's, .tag files) that I need in my maven project. To solve this I have created a "resource" jar from these other projects and have specified them as a dependency in maven. I then unzip the jar (in ant, during the generate-sources lifecycle phase) and copy files to where they need to go. This is where the question is (suggestions on a better overall approach are also welcome). I was thinking I could just move these files into the target directory where I want them and they'd be packaged with the war, but that doesn't work. The common approach seems to be to add an additional resource directory to the war plugin:
How create file and put it in a war with Maven?
Rename a generated file in Maven before building WAR
However, I really don't want to keep these files around in my source code, since they belong to another project. Is there a way I can include temporary resources into the jar?
I would say that this is a typical case when you should be looking at Maven War Overlay.
Overlays are used to share common resources across multiple web applications. The dependencies of a WAR project are collected in WEB-INF/lib, except for WAR artifacts which are overlayed on the WAR project itself.
It means that you can take pieces of another war and apply to your own war. The best thing would be if all the common resources would be in one parent war that would be used by other wars using the overlay technique.
You add a dependency to the war you want to use as an overlay:
<dependency>
<groupId>com.acne</groupId>
<artifactId>acne-web-style</artifactId>
<type>war</type>
<scope>compile</scope>
</dependency>
Then you apply it in the maven-war-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<overlays>
<overlay>
<groupId>com.acne</groupId>
<artifactId>acne-web-style</artifactId>
<includes>
<include>**/resources/*.jpg</include>
</includes>
</overlay>
<overlay>
<!-- empty groupId/artifactId represents the current build -->
</overlay>
</overlays>
</configuration>
</plugin>

Sharing common resources between non-JAR maven projects

I have several Maven projects, say a,b,c, inheriting from a single parent (let's call it parent), and also being modules (of a different project than parent, let's call it super).
These projects all have a pom packaging. Each of these projects has specific configuration, but they also have a common part. To be more speficic, each project two JMeter test configuration files: one specialized for the given project, and another one that is common and identical for all projects.
The problem is - how should I configure the POMs so this common config file is shared among the projects?
A workaround would be to merge all of them into super, and use profiles. However, in this case, I would have to do a separate build for each configuration manually (whereas now I can just build super).
There are similar questions, like this one, but they deal with the jar plugin, which is not relevant for this case.
Structure, for reference:
POM Inheritance:
parent
|
-------------
| | |
a b c
File structure:
super
|
|-a
|
|-b
|
|-c
I have used the maven-remote-resources-plugin for a similar purpose. Create a separate resources project (com.company:resourceProj) of type jar. Put the JMeter resource files in /src/main/resources.
/src/main/resources/common.properties (your filenames obviously)
/src/main/resources/a.properties
etc.
Follow the directions in the example to create the bundle.
Now, add this config to your parent POM (in a testing profile if you want):
<properties>
<shared.resources.dir>${project.build.directory}/shared-resources</shared.resources.dir>
</properties>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<executions>
<execution>
<id>load-resources</id>
<phase>initialize</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<resourceBundles>
<resourceBundle>com.company:resourceProj:version</resourceBundle>
</resourceBundles>
<attached>false</attached>
<outputDirectory>${shared.resources.dir}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Now, tell Maven these are test resources. If your test resource elements are consistent across the modules, this can go in the parent too, if they are different it goes in the module POM. (In my experience with Maven 3 resources defined in a child project take precedence over the parent's; they aren't merged.)
<testResources>
<testResource>
<directory>${shared.resources.dir}</directory>
<includes>
<include>common.properties</include>
<include>${module.file}.properties</include>
</includes>
</testResource>
<!-- any other test resources here -->
</testResources>
In the child module, define the resources module property (this is module a):
<properties>
<module.file>a</module.file>
</properties>
Adapt this to meet your use case.
---- Edit ----
If the configuration is placed into a parent POM, the parent POM may fail to build depending on what configuration is provided by the child. When we are building the shared base/parent projects we don't want to require that all of the properties that should be provided by child projects (inheriters) are defined. So we activate this profile when building the shared projects to bypass anything that only applies to children.
To do this, add an empty file pom-packaging.marker to the parent project's basedir. Then add this profile to the parent POM. When the parent project is built, Maven will find the marker file, enable the profile, and disable all of the executions included in the profile. When a child project is built, the marker file doesn't exist, so the configuration in the main part of the POM will take effect.
I've used this technique with the Enforcer plugin as well - the parent defines the enforcer rules that should be applied to projects inheriting from the parent, but cannot satisfy the rules when it is built. If the plugin provides a "skip" property, you may enable that in this profile instead of using phase = none in plugin configuration.
<profile>
<id>pom-packaging</id>
<activation>
<file>
<exists>pom-packaging.marker</exists>
</file>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<executions>
<execution>
<id>load-resources</id>
<phase>none</phase> <!-- disables this execution -->
</execution>
</executions>
</plugin>
.... other plugin executions here ....
</plugins>
</build>
</profile>
The idea with import scope dependencies is that you can put shared resources into a separate project, which is then imported by a number of other ones; I was thinking you could include your shared config file in this way.
You create a new project with packaging pom (maybe at the same level as the parent?), and then include it in the parent's dependencyManagement section with scope import. Each of your child projects can then receive it by inheritance. It might seem like overkill to make an entire project for just a single file, but I wouldn't have a problem with that.
I haven't actually tried this with a tree of pom-packaged projects, so you might have to play around a bit, but the approach I think is sound. There's a (very extensive) example here:
Importing Dependencies

Order of maven multi module is not maintained for eclipse plugins

We have a bunch of eclipse plugin projects, features and update sites. We have created a master pom where we define the modules:
<modules>
<module>bundles/b1</module>
<module>features/f1</module>
<module>p2/site1</module>
<module>bundles/b2</module>
</modules>
We wanted to preserve this order and as per Guide to working with Multiple Modules
As per the link above we assumed that the order will be preserved as per the order in which the module elements were listed.
Our requirement:
site1 produces a site_assembly.zip. We wanted to take this zip file and wrap into around into a bundle which is what "b2" bundle does.
Our observation:
Maven reactor order which is printed at the beginning of the multi-module build is proper, however the build for every module is forked.
Because of (1) the bundle b2 get built before the site1 project is build and is able to produce a site assembly zip.
We tried adding a dependency in "b2"'s pom.xml to site1 but the build failed as it tries to build b2 first which has dependency on site1 which has not been built till now.
We observed the same behavior when we had unit test as osgi fragment. In the order we clearly specified that the host comes before the test fragment but when the maven build is invoked then it always built the fragment before the host and it used to fail.
Plugins that are defined in master pom:
<plugin>
<!-- enable tycho build extension -->
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-maven-plugin</artifactId>
<version>${tycho-version}</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>target-platform-configuration</artifactId>
<version>${tycho-version}</version>
<configuration>
<disableP2Mirrors>true</disableP2Mirrors>
<resolver>p2</resolver>
<target>
<artifact>
<groupId>com.x.y</groupId>
<artifactId>p2.build.target</artifactId>
<version>${project.version}</version>
<classifier>x</classifier>
</artifact>
</target>
</configuration>
</plugin>
We are not sure if maven-tycho-plugin interferes with the reactor order, so any help would be appreciated.
Tycho resolves the dependencies from the Eclipse descriptor files (MANIFEST.MF, feature.xml, etc.) and re-orders the modules so that required artifacts are built first.

correct use of the exclude term in maven assembly plugin

short: I need to filter all .java files and every META-INF folder from a set of jars and package the class files and resources from that jars into one single jar.
I currently use the maven-assembly-plugin, but would try something else as long as it can easily be integrated into a maven build process.
long: I use maven to manage different stages of development for my tool. basic stage is freeware, second has some more features, third stage is all features)
That works fine so far, I use profiles to add the different source directories to the classpath and the sources are neatly compiled into the project.jar.
First problem: The .java sources included into the project via the profiles end up in the project.jar.
Then I use the maven-assembly-plugin to construct a final.jar that also contains the dependencies and in the end use launch4j to produce an executable for windows (the current target platform).
Second problem: The various META-INF parts from the dependency jars mix in the final.jar and I would want them all to be skipped.
I have searched for examples of the assembly.xml using the <exclude> tag, but did not find any that used my combination of dependencySet and <exclude>*.java</exclude>. I'm not even positive that I can do that.
Here is my assembly.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>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
<useDefaultExcludes>true</useDefaultExcludes>
<!--<useTransitiveFiltering>true</useTransitiveFiltering>-->
<!--<useStrictFiltering>true</useStrictFiltering>-->
<excludes>
<exclude>META-INF</exclude>
<exclude>**/*.java</exclude>
<exclude>*.java</exclude>
<exclude>*:sources</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>
My research so far:
I have googled with example assembly.xml exclude java but could not find examples that covered my problem. (I have also googled a lot the past days but did not save all I found)
I have read http://maven.apache.org/plugins/maven-assembly-plugin/advanced-descriptor-topics.html but could not apply that knowledge to my problem.
Okay, so I figured it out for me.
first: to filter out java and other source files from source parts that were included using profiles I use:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>de.steamnet.oneClickWonder.awt.OCWController</mainClass>
</manifest>
</archive>
<excludes>
<exclude>**/*.java</exclude>
<exclude>**/*.form</exclude>
</excludes>
</configuration>
</plugin>
The task of filtering the META-INF from the dependencies has gone away when I started using an installer so now I can just deliver mulitple jars with their own META-INF.
So, as Michael-O stated this approach (using profiles to include additional source parts) may not be the correct one to do but it is very handy and I stick to it. With the excludes tag from the jar plugin the troubles with source files being added to the final jar also goes away.
This is absolutely the wrong way to go. Do never produce more than one main jar per artifact id. You should use this approach:
create for every main jar a single module.
set dependencies from say full to basic and so forth.
now you have to options to repackage your stuff. You either use the shade plugin which will include the artifact the way you want/need or you use the dependency:unpack-dependencies and put the stuff in the output dir.
After that your will end up with the "aggregated" jar files. Doing that with profiles and asm plugin simply does not scale.
After you have done that create another module for the tar.gz or your distro and depend on that main jars and bundle up your assembly. You are done!
Viel Erfolg und Gruß nach Düren

Resources