Generate several war for spring boot application - maven

It seems that spring boot will repackage the package generated by maven package phase, and then repacke the war to make it executable.
Now I want to genrate multiple wars for different environments by a single maven command, I tried to use maven-assembly-plugin:
1 unzip the war generated by `spring-boot-maven` plugin to a directory
2 Assembly with the files in the directory, and add some other filtered resources
3 create the war
Check this post:generate multiple artifacts in maven
While it works, and I got multiple wars, but none of them can be executeable by java -jar xx.war. It seems that the classes are corrupted.
So I wonder if there is an alternative solution?
update my pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.1.RELEASE</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>src/main/as-common</source>
<source>src/main/as-server</source>
<source>src/main/as-app</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>release</id>
<build>
<plugins>
<!-- unzip the contents of the war(executeable) generated by spring-boot to a certain directory -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>extract_spring_war</id>
<phase>package</phase>
<configuration>
<target>
<echo message="extract war generated by spring-boot-maven-plugin"/>
<delete dir="${basedir}/target/${project.build.finalName}-spring" includeemptydirs="true"/>
<unzip src="${basedir}/target/${project.build.finalName}.war" dest="${basedir}/target/${project.build.finalName}-spring/"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<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>dep1</item>
<item>dep2</item>
</items>
<pluginExecutors>
<pluginExecutor>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
</plugin>
<goal>single</goal>
<configuration>
<archive>
<manifest>
<mainClass>org.springframework.boot.loader.WarLauncher</mainClass>
</manifest>
</archive>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</pluginExecutor>
</pluginExecutors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
assmbly.xml:
<assembly>
<id>${item}</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<!-- file from the unpacked contents -->
<fileSet>
<directory>target/${project.build.finalName}-spring</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*</include>
</includes>
<filtered>true</filtered>
</fileSet>
<!-- add environment awared resources -->
<fileSet>
<outputDirectory>/WEB-INF/classes</outputDirectory>
<directory>${basedir}/src/main/custom/</directory>
<includes>
<include>${item}.properties</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Update:
At first I got the error:
No main class detected
Then I add the following for maven-assembly-plugin,
<archive>
<manifest>
<mainClass>org.springframework.boot.loader.WarLauncher</mainClass>
</manifest>
</archive>
After that I repackage the wars, and I got error when I ran:
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 4022320623 in class file org/springframework/boot/loader/WarLauncher

The class files are being corrupted when you're repackaging the war file. I suspect that's because you're filtering all of the files:
<fileSet>
<directory>target/${project.build.finalName}-spring</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*</include>
</includes>
<filtered>true</filtered>
</fileSet>
You don't want to filter binary files as they may happen to contain data that looks like a ${} placeholder. You should update the assembly to avoid applying the filtering to class files. The simplest way to do that would be to disable filtering entirely:
<fileSet>
<directory>target/${project.build.finalName}-spring</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*</include>
</includes>
<filtered>false</filtered>
</fileSet>
If you need filtering for text files, you should use two fileSets. One that includes the binary files and disables filtering, and one that includes the text files and enables filtering.

Related

copy the content of a directory of maven module project into another module

I want to copy the content of a directorymodule maven project.
Here is the hierarchy
I want to copy the content of dist directory into Tourism/Tourism-Services/src/main/webapp directory
For this purpose, I tried to use maven-assembly-plugin
here is the extract of the relative pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>./</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>cfg-main-resources</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>${basedir}/src/main/angular5/tourism/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
Here is the extract of assembly.xml 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>distribution</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<outputDirectory>./</outputDirectory>
<directory>src/main/angular5/tourism/dist</directory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
The problem is that the content of dist directory is copied in Tourism/Tourism-Web/target directory. I would like to copy this content in another module, in Tourism/Tourism-Services/src/main/weapp directory. Thank you for your help
I succeded in configuring the pom.xml's
Here is an extract of pom.xml within Tourism-Web sub-module
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>true</appendAssemblyId>
</configuration>
<executions>
<execution>
<id>cfg-main-resources</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>${basedir}/src/main/angular5/tourism/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
Here is an extract of 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>assembly</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<outputDirectory>./</outputDirectory>
<directory>src/main/angular5/tourism/dist</directory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
Here is an extract of pom.xml of Tourism-Services sub-module
<dependencies>
<dependency>
<groupId>tourism-guide</groupId>
<artifactId>tourism-web</artifactId>
<version>${project.version}</version>
<classifier>assembly</classifier>
<type>zip</type>
<scope>compile</scope>
</dependency>
..................
's..................
</dependencies>
<build>
<!-- Set the name of the war, used as the context root when the app is
deployed -->
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-angular-dist-resources</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>compile</phase>
<configuration>
<outputDirectory>${basedir}/src/main/webapp</outputDirectory>
<includeArtifactIds>tourism-web</includeArtifactIds>
<includeGroupIds>${project.groupId}</includeGroupIds>
<excludeTransitive>true</excludeTransitive>
<excludeTypes>pom</excludeTypes>
<scope>compile</scope>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Thank you for reading

maven assembly plugin: descriptorRef not using basedir

I am using maven assembly plugin to zip my web application dist folder.
I use this descriptorRef file:
<assembly>
<id>webapp-build</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>dist</directory>
<outputDirectory>.</outputDirectory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
and I use it as a dependency in a parent pom like this:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<dependencies>
<dependency>
<groupId>com.company</groupId>
<artifactId>build-tools</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>webapp-build</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptionRef>webapp-build</descriptionRef>
</descriptorRefs>
<basedir>${project.assembly.directory}</basedir>
</configuration>
</execution>
</executions>
</plugin>
Depending on the child using this parent pom, I would like to tell in which directory, the maven assembly plugin has to use the webapp-build assembly descriptor. I tried with <basedir> attribute but it is not using it. Any ideas ?
The descriptorRef is intended to load assembly descriptors from classpath or using predefined descriptors. If you like to use the given descriptor you have to use descriptors instead like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>assemblies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Furthermore a basedir configuration element does not exist for maven-assembly-plugin:single
<basedir> isn't a parameter of assembly:single. There's descriptorSourceDirectory:
descriptorSourceDirectory:
Directory to scan for descriptor files in. NOTE: This may not work correctly with assembly components.

Maven: Build tar.gz file with externally downloaded files

What I'm trying to do with maven is build a project.tar.gz file with some data in the ./data folder downloaded from some location on the web.
project.tar.gz
data
somefile.txt
some_other_file.zip
Currently I'm trying to approach this using the assembly plugin, so far without much success.
So far the following works: I download a file to target/data
But now I need that file packaged in a tar file.
<build>
<plugins>
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>http://www.lolcats.com/images/u/08/23/lolcatsdotcomcm90ebvhwphtzqvf.jpg</url>
<outputDirectory>${project.build.directory}/data</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
I ended up using https://github.com/maven-download-plugin/maven-download-plugin
<build>
<plugins>
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>${some.jar.file.url}</url>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<url>${some.models.zip.url}</url>
<unpack>true</unpack>
<outputDirectory>${project.build.directory}/data</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version> <!-- Old -->
<executions>
<execution> <!-- Build tar.gz archive. -->
<id>tar</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/tar.xml</descriptor>
</descriptors>
<finalName>project-${project.version}-el6</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution> <!-- /NewStuff -->
</executions>
</plugin>
</plugins>
</build>
using tar.xml:
<assembly>
<id>tar</id>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<fileSet>
<directory>target/data</directory>
<outputDirectory>/data</outputDirectory>
</fileSet>
<fileSet>
<directory>target/lib</directory>
<outputDirectory>/lib</outputDirectory>
</fileSet>
<fileSet>
<directory>meta</directory>
<outputDirectory>/meta</outputDirectory>
</fileSet>
</fileSets>
I personally wouldn't use Maven for this; Maven is a tool for standard processes. What you want to do is very special.
Have a look at the Maven AntRun Plugin or use Ant directly. That way, you can create a script which does exactly what you want without fighting with Maven's conventions all the time.

Maven doesn't attach non-archived files with mavenAssemblyPlugin

I have some list of files (.jil).
I'd like to attach them to the build using maven-assembly-plugin.
I have no difficulty deploying these with the "zip"
format.
However, the "dir" format throw an exception:
[WARNING] Assembly file: C:\Branches\project-branch\target\project\output\directory is not a regular file (it may be a directory). It cannot be attached to the project build for installation or deployment.
pom file:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>make-devq</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>
${basedir}/environments/dev/assembly/descriptor.xml
</descriptor>
</descriptors>
<finalName>project</finalName>
<appendAssemblyId>true</appendAssemblyId>
<workDirectory>
${project.build.directory}/${project.artifactId}/work/project
</workDirectory>
<outputDirectory>
${project.build.directory}/${project.artifactId}/output
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
assembly descriptor:
<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>project-id</id>
<formats>
<format>dir</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${basedir}/environments/dev/jils/</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jil</include>
</includes>
</fileSet>
</fileSets>
</assembly>
To add separate files you should use the build-helper-maven-plugin which offers such options to you.
<project>
...
<build>
<plugins>
<plugin>
<!-- add configuration for antrun or another plugin here -->
</plugin>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>some file</file>
<type>extension of your file </type>
<classifier>optional</classifier>
</artifact>
...
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
With the dir format you can't attach these files to your project.
BTW: The current up-to-date version of maven-assembly-plugin is 2.4.
According to Maven doc, the accepted formats are:
dir - Creates a directory zip
Creates a ZIP file format tar
Creates a TAR format tar.gz
Creates a gzip'd TAR format tar.bz2
Creates a bzip'd TAR format

Move a text file into target folder when compiling a Maven project

I have a slight different version of the question that I made recently.
I have a Maven project under Netbeans 7.3, which doesn't have any build.xml file to configure building options, while there is the pom.xml that I use to import other libraries. Now, I have a text file (let's say textfile.txt) stored in the project folder in Netbeans 7.3, e.g.
project folder
textfile.txt
src
package
package.subpackage
MyClass.java
When I compile I get a target folder where the jar file is put in, e.g.
project folder
textfile.txt
target
classes
generated-sources
....etc
test-classes
MyProject.jar
src
package
package.subpackage
MyClass.java
How can I make the file textfile.txt being copied under target folder when I compile the Maven project?
A first way is to put the files into src/main/resources that is the folder devoted to store the complied resources, i.e. the resources included into the jar file (e.g. images for the icons).
If you need to make the config file to be distributed with the jar, but separated by it, you must edit the pom.xml file. A possible answer is the to add the following plugin between the <plugins> and </plugins> tags.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo>Using env.test.properties</echo>
<copy file="textfile.txt" tofile="${basedir}/target/textfile.txt"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
Moreover, as you can read here you can also import all the resources from an "input" directory to an "output" directory inside target by using the dedicated plugin, e.g.:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/output</outputDirectory>
<resources>
<resource>
<directory>input</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
The simplest way, to use some resource as I know (additional information about resources configuration you can find here: https://maven.apache.org/plugins/maven-resources-plugin/):
<build>
<plugins>
<!-- your plugins, including or not maven-resource-plugin -->
</plugins>
<resources>
<resource>
<filtering>true</filtering><!-- if it is neccessary -->
<directory>${project.basedir}</directory><!-- from -->
<targetPath>${project.build.directory}</targetPath><!-- to -->
<includes><!-- what -->
<include>textfile.txt</include>
</includes>
</resource>
</resources>
</build>
For building my setting files and updating production this worked for me:
<build>
<resources>
<resource>
<directory>${project.basedir}</directory><!-- from -->
<targetPath>${project.build.directory}</targetPath><!-- to -->
<includes><!-- what -->
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
To have an absolute control of the output of your build you can use the "Apache Maven Assembly Plugin". You can define pretty much everything (format, subfolders...).
The Assembly Plugin for Maven is primarily intended to allow users to aggregate the project output along with its dependencies, modules, site documentation, and other files into a single distributable archive.
More info
You have to install the plugin in your pom file:
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/yourassembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>x.x</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/yourassembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- append to the packaging phase. -->
<goals>
<goal>single</goal> <!-- goals == mojos -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
In your case the descriptor "yourassembly.xml" would be as follows:
<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>yourassembly</id>
<formats>
<format>tar.gz</format>
<format>dir</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.basedir}</directory>
<includes>
<include>README*</include>
<include>LICENSE*</include>
<include>NOTICE*</include>
</includes>
<useDefaultExcludes>true</useDefaultExcludes>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${basedir}</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>textfile.txt</include>
</includes>
</fileSet>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
</fileSets>
</assembly>

Resources