Creating output dir structure with Maven - maven

I have a java project XXX
src/main/java
src/main/config
src/main/scripts
I want output structure like
C:/target/XXX.jar
C:/target/scripts
I tried to use resource plugin but it is packing everything inside jar.
<build>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<finalName>${artifactId}-${version}</finalName>
<sourceDirectory>src/main/java</sourceDirectory>
<scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<resources>
<resource>
<directory>src/main/config</directory>
</resource>
<resource>
<directory>src/main/scripts</directory>
<targetPath>/scripts</targetPath>
</resource>
</resources>
</build>

The maven-assembly-plugin is great for this sort of thing. You can create a descriptor something like this (in src/main/assemble/scripts.xml):
<assembly>
<id>scripts</id>
<formats>
<format>dir</format>
</formats>
<fileSets>
<fileSet>
<outputDirectory>/scripts</outputDirectory>
<includes>
<include>*.*</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Wire this into your build like so:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptors>
<descriptor>src/main/assemble/scripts.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>copy-scripts</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
This will bind the execution of the assembly to the package phase of the build.
This method will give you the flexibility to change how you package up the scripts in the future, or copy more resources in the build.

Related

Maven - How to create a POM that place files in the root

I need to create a pom.xml file that builds a jar with certain files place on its root. The pom.xml I have now creates 3 directories BOOT-INF, META-INF and org. Below is the build section. I want the files to be at the same level as the directories (BOOT-INF, META-INF, org).
sparc-jar.jpg
<plugins>
<plugin>
<groupId>oerg.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.sh</include>
<include>**/*.id</include>
<include>**/*.yaml</include>
<include>**/*.json</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.jar</include>
<include>**/*.js</include>
<include>**/*.map</include>
<include>**/*.html</include>
<include>**/*.hbs</include>
<include>**/*.cer</include>
<include>**/*.p12</include>
</includes>
</resource>
<resource>
<directory>.</directory>
<includes>
<include>**/*.yaml</include>
<include>**/*.json</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
<include>**/*.cer</include>
<include>**/*.p12</include>
</includes>
</resource>
</resources>
</build>
This worked for me... Configure the spring-boot-maven-plugin as follows:
<configuration>
<outputDirectory>${project.basedir}</outputDirectory>
</configuration>

How can a jar with specific deps be created, after using maven-dependency-plugin to select the wanted deps?

My goal is to create a jar with specific dependencies from my dependency list in the pom. I'm using maven-dependency-plugin like so:
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<includeScope>runtime</includeScope>
<excludes>META-INF/*.SF,META-INF/*.DSA,META-INF/*.RSA</excludes>
<outputDirectory>${project.build.directory}/uber-deps/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.some.blaClass</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
and an assembly.xml file holding:
<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>plugin</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
<includes>
<include>
${project.build.directory}/uber-deps/
</include>
</includes>
<excludes>
<exclude>*:sources</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>
After mvn clean install all relevant dependencies appear in target/uber-deps as I would expect. My problem is with the next plugin under <plugins> - maven-assembly-plugin. Seems to me as if it doesn't take uber-deps in.
I know this only by trying to unpack the jar using jar xf to see if the deps in uber-deps were packed in the jar created after mvn clean install.
What should be changed?
1)
The jar you are building as part of the assembly-plugin will be called (by default) ./target/<artifactId>-plugin.jar
Note that the plugin part is what you've put under id in your assembly xml file.
2)
Since you already unpack the dependencies to a folder, you should use fileSets rather then dependencySets:
<fileSets>
<fileSets>
<fileSet>
<outputDirectory>/</outputDirectory>
<includes>
<include>
${project.build.directory}/uber-deps/
</include>
</includes>
</fileSet>
</fileSets>
</fileSets>
3)
BTW if you want the outputs of your own project in that jar you should add another fileSet:
<fileSet>
<outputDirectory>/</outputDirectory>
<includes>
<include>
${project.build.outputDirectory}
</include>
</includes>
</fileSet>
4) Also just noted that your assembly plugin definition is not stating the location of your assembly xml file and that you try to define mainClass using shade-plugin configuration. This is how it should look in assembly plugin (assuming that your assembly file is located under src/assembly/plugin.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>src/assembly/plugin.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>com.some.blaClass</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>

Move resource files to target and exclude from jar

I have a maven project set up like this:
\src
\--main
\--java
\--fu
\--bar
\--AppMain.java
\--resources
\--log4j.xml
With a pom using the maven-resources-plugin to move my resource files to a target directory like this:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>my/target/dir/config</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
And the maven-jar-plugin to create the jar like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>fu.bar.AppMain</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
When I run mvn clean install, my target location includes the compiled jar and the \config\log4j.xml. However, the jar also includes log4j.xml.
How do I exclude log4j.xml from the jar and still move it to \my\target\dir\config?
Adding this to my pom was the trick:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
</build>

Generate several war for spring boot application

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.

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