Maven shade copy WEB-INF - java

Using maven-shade-plugin I am trying to create a project file structure as follows:
The problem is that the following pom configuration is not creating the WEB-INF directory.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<createDependencyReducedPom>true</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.my.package.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Basically I need to copy my web.xml file, classes and lib files into a directory called WEB-INF in the root of the project.
Update: SORRY, I copied the wrong plugin from my pom into the original question!
Update: If I add the packaging from the pom declaration: <packaging>war</packaging> The WEB-INF file structure is completed as per the OQ. However, with this declaration the com directory now does not contain my packages so the main class cannot be found.
How it looks with the <packaging>war</packaging>:
How it should look:

maven-assembly plugin allows much more flexibility, it would be easily accomplished by using assembly plugin
See
assembly descriptor examples

There are lots of possible answer to achieve the desired effect with maven. However, based on the update I gave I found that adding the maven-antrun-plugin with the following solved my issue:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>move-main-class</id>
<phase>compile</phase>
<configuration>
<tasks>
<copy todir="${project.build.directory}/${project.artifactId}">
<fileset dir="${project.build.directory}/classes/">
</fileset>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

Related

JMH + Maven. BenchmarkList gets in wrong JAR

I've encountered a little problem with a project that I considered finished.
It includes three parts -- the main class for which the whole project was created (a quadruple-precision floating-point number with necessary arithmetic), a set of tests for it, and a benchmarking tool for it which uses JMH. Accordingly, the pom.xml is supposed to build three jar-files -- Quadruple-1.0.0.jar, Quadruple-1.0.0-tests.jar, and benchmarks.jar. And it does, but the problem is that it puts BenchmarkList in the Quadruple-1.0.0-tests.jar instead of benchmarks.jar.
Thereafter, an attempt to execute the benchmarks running the benchmarks.jar fails with the message
Exception in thread "main" java.lang.RuntimeException: ERROR: Unable to find the resource: /META-INF/BenchmarkList
at org.openjdk.jmh.runner.AbstractResourceReader.getReaders(AbstractResourceReader.java:98)
at org.openjdk.jmh.runner.BenchmarkList.find(BenchmarkList.java:124)
at org.openjdk.jmh.runner.Runner.internalRun(Runner.java:253)
at org.openjdk.jmh.runner.Runner.run(Runner.java:209)
at org.openjdk.jmh.Main.main(Main.java:71)
Below is the relevant part of the pom.xml:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javac.target>1.8</javac.target>
<jmh.version>1.29</jmh.version>
<uberjar.name>benchmarks</uberjar.name>
<junit.jupiter.minorVersion>2.0</junit.jupiter.minorVersion>
</properties>
...
<build>
<plugins>
....
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>${uberjar.name}</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.openjdk.jmh.Main</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
<filters>
<filter>
<!--
Shading signed JARs will fail without this.
http://stackoverflow.com/questions/999489/invalid-signature-file-when-attempting-to-run-a-jar
-->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>test-jar</id>
<phase>package</phase>
<goals>
<goal>test-jar</goal>
</goals>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>libs/</classpathPrefix>
<mainClass>
com.mvohm.quadruple.test.QuadTest
</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
At the same time in a neighbor folder I have a very similar project, which is actually just a previous version of the benchmarking tool, and it builds and works fine. After a number of attempts to figure out what is the reason of such a difference in their behavior, their poms became almost identical. The only difference is that the separate benchmarking project has one additional dependency (to import Quadruple), and the names of the projects are different, and there's no test subfolder in the src folder of the benchmarking project, thus the Quadruple_Benchmarks-0.0.1-SNAPSHOT-tests.jar contains nothing except MANIFEST.MF.
What may be the reason of getting BenchmarlList to the wrong jar? Generally, who is responsible for putting it in the benchmarks.jar and not in any other jar?
If any additional information turns out to be relevant and can help clarify the situation, I'm ready to promptly provide it. The complete poms (in their previous states, yet with the same behavior) are accessible at github:
https://github.com/m-vokhm/Quadruple/blob/master/pom.xml, (main project)
https://github.com/m-vokhm/QuadrupleAddendum/blob/master/QuadBenchmarks/pom.xml (old benchmarks)

Maven shade plugin: why original jar contains all the dependency (just like the shaded jar)

I created a general shade plugin instance below
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<filters>
<filter>
<artifact>*:*<artifact/>
<excludes>
<exclude>META-INF/*.gif</exclude>
<excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
However when executing mvn clean package I found the original- jar is the same size of the shade jar and contains all the dependency library, what could be the cause of such incident
original-myapp-0.0.1-SNAPSHOT.jar 168Mb
myapp-0.0.1-SNAPSHOT.jar 168Mb

"Deleting" the generated default jar in Maven

There are solutions available to "disable" the default jar that is generated by the maven-jar-plugin. However, since my final artifacts probably depend on this jar (I am relatively new to maven, so not entirely sure if it is actually the case, but it seems so) when I disable it, my build fails with the following error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:2.3:shade (build-cli) on project putwb: Failed to create shaded artifact, project main artifact does not exist. -> [Help 1]
Otherwise, it produces an empty jar along with the other jars I am building through my scripts. Can somebody suggest a way to "delete" the default jar, after the build is complete? Alternatively, can someone point out how I can disable that yet my build succeeds?
I am posting the relevant part of my pom.xml below:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>readme-md</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>README.md</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<!-- Build the CLI version -->
<phase>package</phase>
<id>build-cli</id>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<!-- Don't include the UI code -->
<filter>
<artifact>*:*</artifact>
<excludes>in/ac/iitk/cse/putwb/ui/**</excludes>
</filter>
</filters>
<finalName>putwb-cli-${project.version}</finalName>
<transformers>
<!-- Don't include images -->
<transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
<resource>.png</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>in.ac.iitk.cse.putwb.experiment.PUTExperiment</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
<execution>
<!-- Build the UI version -->
<phase>package</phase>
<id>build-ui</id>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>putwb-ui-${project.version}</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>in.ac.iitk.cse.putwb.ui.PUTWb</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<!-- If I add this to the script, the build fails -->
<!--
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<executions>
<execution>
<id>default-jar</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
-->
</plugins>
</build>
You can use ant-run plugin's delete task. You can execute this plugin in any phase that is later than package phase in the life cycle.(because it will be created again in package phase. Check which one suites you better.) Execute the maven command you choose as this plugins phase (like mvn verify if you choose verify phase)
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<delete file="${project.build.directory}/YourJarName.jar"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
Check Build life cycle https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
thanks to #markthegrea for pointing the correct folder.

Create jar with dependencies and excluding specific source files

I would like to use Maven to create a jar that includes a specific dependent artifact and excludes some of the source java files.
Currently I use this snippet:
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>shadedJar</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedClassifierName>classifier</shadedClassifierName>
<shadedArtifactAttached>true</shadedArtifactAttached>
<createDependencyReducedPom>false</createDependencyReducedPom>
<artifactSet>
<includes>
<include>com.google.guava:guava</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
Thus, the jar does contain the 'guava' artifact files, however I would also like to exclude some source files (for example a specific file under src/main/java/my.package/), How can I do that?
I use shade to create a jar, but I do not need some files of eclipse, txt and other things that they are relevant only to development.
This is the code I have, maybe you can addapt it and use it.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>.settings/**</exclude>
<exclude>*.classpath</exclude>
<exclude>*.project</exclude>
<exclude>*.txt</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>

Merge properties files with Maven assembly

I have a problem with maven assembly plugin.
I have a maven project which use several jars. Each jar contains configuration files.
With another project, I use maven assembly plugin to assemble all configurations in unique jar.
All work fine but unfortunately, two files are the same name and the second overwrites the first.
I don't achieve to tell maven to merge the two files instead of overwrite.
Someone knows how to do that ?
Thanks.
The maven-shade-plugin combined with the AppendingTransformer should do what you want.
We use it to merge together the properties files from two zip projects, defined as separate maven modules, into a single zip file. This creates the superset of the files and directories from the two modules and merges together the specified properties file. We also define the module to merge as a dependency of the maven module doing the merge.
Something like this should do the trick:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>groupname:artifactname</artifact>
<includes>
<include>**/*</include>
</includes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>propertyfiletomerge.properties</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
It is not exactly what you are looking for, but I would use http://maven.apache.org/plugins/maven-antrun-plugin/ plugin to run ant concat task http://ant.apache.org/manual/Tasks/concat.html to merge the files. I would run the maven-antrun in prepare-package phase.
Based on Skarab's answer, here's the code I used to solve this issue using the maven-antrun-plugin:
<project>
...
<build>
...
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>prepare-package</phase>
<configuration>
<target>
<concat destfile="${project.build.directory}/setup_db.sql">
<fileset file="${project.basedir}/src/main/resources/db/sql_one/*.sql" />
<fileset file="${project.basedir}/src/main/resources/db/sql_another/*.sql" />
</concat>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
You could might try to rename the first file and merge the two files after that.
Here is a Thread on stackoverflow, where the renaming of such a file is documentated:
Renaming resources in Maven

Categories

Resources