JMH + Maven. BenchmarkList gets in wrong JAR - java

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)

Related

Maven creating incorrect manifest file, jar file isn't executable, because main class isn't specified

I'm trying to produce a .jar file that I can execute through command prompt. I am using Maven with this project so that I can use Unirest (to get data through a realtor API). First, however, I am trying to compile a simple "hello world" program to an executable .jar file, and Maven isn't adding the main-class attribute to the Manifest file. I used the instructions on this website under the "Maven Assembly Plugin" section. Here's the relevant portion of the pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>com.javaRealtor.app.App</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
The .java file is located at java-realtor\src\main\java\com\javaRealtor\app\App.java. Do I need to specify the MainClass part of the plugin differently? I tried using just com.javaRealtor.App as well, but that didn't work. The manifest file (I extracted the jar to view it so I could maybe figure out what was going on) still doesn't have a line for a main class.
You need to use shade plugin for this transformation
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.javaRealtor.app.App</Main-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Just a note: please avoid camel case in packaging name in order to:
avoid problem managing multiple dev platforms (case sensitive: linux/unix and case insentive Windows)
be complain with Java Conventions

java.lang.NoClassDefFoundError in Maven shaded jar for salesforce API jars

I have an Apache Maven Java project that imports the class:
com.sforce.soap.enterprise.EnterpriseConnection
When running the project from IntelliJ, I have no problems executing the code. However, I want to be able to run the project from the command line as a shaded jar. I have been shading the jar using 'mvn package'. When I run the jar from the command line I am getting the error:
Exception in thread "main" java.lang.NoClassDefFoundError: com/sforce/soap/enterprise/EnterpriseConnection
My pom includes dependencies:
<dependency>
<groupId>qa-integration.sfdc</groupId>
<artifactId>enterprise</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/enterprise-1.0.0.jar</systemPath>
</dependency>
<dependency>
<groupId>qa-integration.sfdc</groupId>
<artifactId>metadata</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/metadata-1.0.0.jar</systemPath>
</dependency>
My shade execution looks like the following:
<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>false</createDependencyReducedPom>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.sunrun.integration.sfdc.metadata.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
When I list the contents of the jar, I see no salesforce files at all.
I had this problem and my solution was to add the following snippet to my pom.xml:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>corrigo.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!--<plugin>-->
<!--<groupId>org.apache.maven.plugins</groupId>-->
<!--<artifactId>maven-jar-plugin</artifactId>-->
<!--<version>2.4</version>-->
<!--<configuration>-->
<!--<archive>-->
<!--<manifest>-->
<!--<mainClass>corrigo.Main</mainClass>-->
<!--</manifest>-->
<!--</archive>-->
<!--</configuration>-->
<!--</plugin>-->
</plugins>
</build>
Then you just run mvn package.
Here is a reliable resource:
https://www.mkyong.com/maven/how-to-create-a-jar-file-with-maven/

Maven shade copy WEB-INF

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>

Netbeans Maven Project Not adding Main Class to Manifest

I am having a similar problem to this question. I have tried all the suggestions listed and am still at a loss. My issue is that I am trying to build a maven project and distribute it to other machines, but the jar files are not being populated with a correct Manifest. Each time I build and run I get the following error: no main manifest attribute, in myjar.jar. Is there some sort of configuration file I need to edit? I just don't know what is going on. I have attempted this fix also, but to no avail.
You can add it into project's pom file, inside <project> tag:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<mainClass>your.main.class</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
Another option is to use the maven shade plugin. Unlike the maven jar plugin showed by tigran, the maven shade plugin includes your dependencies in the generated jar.
A sample usage of the plugin is :
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>your.main.Class</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

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