Related
My java program is packaged in a jar file and makes use of an external jar library, bouncy castle. My code compiles fine, but running the jar leads to the following error:
Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
I've googled for over an hour searching for an explanation and found very little of value. If anyone has seen this error before and could offer some help, I would be obliged.
For those who got this error when trying to create a shaded uber-jar with maven-shade-plugin, the solution is to exclude manifest signature files by adding the following lines to the plugin configuration:
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<!-- Additional configuration. -->
</configuration>
For those using gradle and trying to create and use a fat jar, the following syntax might help.
jar {
doFirst {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}
Please use the following command
zip -d yourjar.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*.DSA'
Some of your dependencies are likely signed jarfiles. When you combine them all into one big jarfile, the corresponding signature files are still present, and no longer match the "big combined" jarfile, so the runtime halts thinking the jar file has been tampered with (which it...has so to speak).
Assuming you're using ant, you can solve the problem by eliminating the signature files from your jarfile dependencies. Unfortunately, it's not possible to do this in one step in ant.
However, I was able to get this working with Ant in two steps, without specifically naming each jarfile dependency, by using:
<target name="jar" depends="compile" description="Create one big jarfile.">
<jar jarfile="${output.dir}/deps.jar">
<zipgroupfileset dir="jars">
<include name="**/*.jar" />
</zipgroupfileset>
</jar>
<sleep seconds="1" />
<jar jarfile="${output.dir}/myjar.jar" basedir="${classes.dir}">
<zipfileset src="${output.dir}/deps.jar" excludes="META-INF/*.SF" />
<manifest>
<attribute name="Main-Class" value="com.mycompany.MyMain" />
</manifest>
</jar>
</target>
The sleep element is supposed to prevent errors about files with modification dates in the future.
Other variations I found in the linked threads didn't work for me.
The solution listed here might provide a pointer.
Invalid signature file digest for Manifest main attributes
Bottom line :
It's probably best to keep the official jar as
is and just add it as a dependency in the manifest file for your
application jar file.
Security is already a tough topic, but I'm disappointed to see the most popular solution is to delete the security signatures. JCE requires these signatures. Maven shade explodes the BouncyCastle jar file which puts the signatures into META-INF, but the BouncyCastle signatures aren't valid for a new, uber-jar (only for the BC jar), and that's what causes the Invalid signature error in this thread.
Yes, excluding or deleting the signatures as suggested by #ruhsuzbaykus does indeed make the original error go away, but it can also lead to new, cryptic errors:
java.security.NoSuchAlgorithmException: PBEWithSHA256And256BitAES-CBC-BC SecretKeyFactory not available
By explicitly specifying where to find the algorithm like this:
SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC","BC");
I was able to get a different error:
java.security.NoSuchProviderException: JCE cannot authenticate the provider BC
JCE can't authenticate the provider because we've deleted the cryptographic signatures by following the suggestion elsewhere in this same thread.
The solution I found was the executable packer plugin that uses a jar-in-jar approach to preserve the BouncyCastle signature in a single, executable jar.
UPDATE:
Another way to do this (the correct way?) is to use Maven Jar signer. This allows you to keep using Maven shade without getting security errors. HOWEVER, you must have a code signing certificate (Oracle suggests searching for "Java Code Signing Certificate"). The POM config looks like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>org.bouncycastle:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>your.class.here</mainClass>
</transformer>
</transformers>
<shadedArtifactAttached>true</shadedArtifactAttached>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>sign</id>
<goals>
<goal>sign</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<keystore>/path/to/myKeystore</keystore>
<alias>myfirstkey</alias>
<storepass>111111</storepass>
<keypass>111111</keypass>
</configuration>
</plugin>
No, there's no way to get JCE to recognize a self-signed cert, so if you need to preserve the BouncyCastle certs, you have to either use the jar-in-jar plugin or get a JCE cert.
I had this problem when using IntelliJ IDEA 14.01.
I was able to fix it by:
File->Project Structure->Add New (Artifacts)->jar->From Modules With Dependencies on the Create Jar From Module Window:
Select you main class
JAR File from Libraries
Select copy to the output directory and link via manifest
I faced the same issue, after reference somewhere, it worked as below changing:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<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>
</configuration>
</execution>
</executions>
</plugin>
Assuming you build your jar file with ant, you can just instruct ant to leave out the META-INF dir. This is a simplified version of my ant target:
<jar destfile="app.jar" basedir="${classes.dir}">
<zipfileset excludes="META-INF/**/*" src="${lib.dir}/bcprov-jdk16-145.jar"></zipfileset>
<manifest>
<attribute name="Main-Class" value="app.Main"/>
</manifest>
</jar>
I've recently started using IntelliJ on my projects. However, some of my colleagues still use Eclipse on the same projects. Today, I've got the very same error after executing the jar-file created by my IntelliJ. While all the solutions in here talking about almost the same thing, none of them worked for me easily (possibly because I don't use ANT, maven build gave me other errors which referred me to http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException, and also I couldn't figure out what are the signed jars by myself!)
Finally, this helped me
zip -d demoSampler.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*SF'
Guess what's been removed from my jar file?!
deleting: META-INF/ECLIPSE_.SF
deleting: META-INF/ECLIPSE_.RSA
It seems that the issue was relevant to some eclipse-relevant files.
I had the same issue in gradle when creating a fat Jar; updating the build.gradle file with an exclude line corrected the problem.
jar {
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
manifest {
attributes 'Main-Class': 'com.test.Main'
}
}
In case you're using gradle, here is a full farJar task:
version = '1.0'
//create a single Jar with all dependencies
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version,
'Main-Class': 'com.example.main'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
with jar
}
Compare the folder META-INF in new jar with old jar (before you added new libraries). It is possibility that there will be new files. If yes, you can remove them. It should helps.
Regards,
999michal
A strategy would consist in using ANT to simplify the removal of the signature from each Jar file. It would proceed with the following steps:
Copying the MANIFEST.MF in a temporary file
Removing the Name and SHA entries from the temporary file
Creating a temporary Jar file with the temporary manifest
Removing the temporary manifest
Swapping the original Jar file with the temporary one
Here is an ANT macrodef doing the work:
<macrodef name="unsignjar" description="To unsign a specific Jar file">
<attribute name="jarfile"
description="The jar file to unsign" />
<sequential>
<!-- Copying to the temporary manifest file -->
<copy toFile="#{jarFile}_MANIFEST.tmp">
<resources>
<zipentry zipfile="#{jarFile}" name="META-INF/MANIFEST.MF"/>
</resources>
</copy>
<!-- Removing the Name and SHA entries from the temporary file -->
<replaceregexp file="#{jarFile}_MANIFEST.tmp" match="\nName:(.+?)\nSH" replace="SH" flags="gis" byline="false"/>
<replaceregexp file="#{jarFile}_MANIFEST.tmp" match="SHA(.*)" replace="" flags="gis" byline="false"/>
<!-- Creating a temporary Jar file with the temporary manifest -->
<jar jarfile="#{jarFile}.tmp"
manifest="#{jarFile}_MANIFEST.tmp">
<zipfileset src="#{jarFile}">
<include name="**"/>
<exclude name="META-INF/*.SF"/>
<exclude name="META-INF/*.DSA"/>
<exclude name="META-INF/*.RSA"/>
</zipfileset>
</jar>
<!-- Removing the temporary manifest -->
<delete file="#{jarFile}_MANIFEST.tmp" />
<!-- Swapping the original Jar file with the temporary one -->
<move file="#{jarFile}.tmp"
tofile="#{jarFile}"
overwrite="true" />
</sequential>
`
The definition can then be called this way in an ANT task:
<target name="unsignJar">
<unsignjar jarFile="org.test.myjartounsign.jar" />
</target>
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:314)
at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:268)
at java.util.jar.JarVerifier.processEntry(JarVerifier.java:316)
at java.util.jar.JarVerifier.update(JarVerifier.java:228)
at java.util.jar.JarFile.initializeVerifier(JarFile.java:383)
at java.util.jar.JarFile.getInputStream(JarFile.java:450)
at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:977)
at sun.misc.Resource.cachedInputStream(Resource.java:77)
at sun.misc.Resource.getByteBuffer(Resource.java:160)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:454)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
What helped me (IntelliJ IDEA 2016.3):
File -> Project Structure -> Artifacts -> Add JAR -> Select Main Class -> Choose "copy to the output directory and link via manifest" -> OK -> Apply -> Build -> Build Artifacts... -> Build
It's possible that two different signers mess up java mind.
Try removing META-INF folder from jar, adding manifest and signing JAR again, it helped me: http://jehy.ru/articles/2013/12/13/invalid-signature-file-digest-for-manifest-main-attributes/
If you are looking for a Fat JAR solution without unpacking or tampering with the original libraries but with a special JAR classloader, take a look at my project here.
Disclaimer: I did not write the code, just package it and publish it on Maven Central and describe in my read-me how to use it.
I personally use it for creating runnable uber JARs containing BouncyCastle dependencies. Maybe it is useful for you, too.
You can use Shadow to generate a jar.
Shadow is a Gradle plugin for combining a project's dependency classes and resources into a single output Jar. The combined Jar is often referred to a fat-jar or uber-jar.
Modify build.gradle
plugins {
...
// ① Add the shadow plugin
id "com.github.johnrengelman.shadow" version "5.2.0"
}
...
// ② Config the shadow jar, its name is baseName-1.0-classifier.jar
shadowJar {
archiveBaseName.set('baseName')
archiveClassifier.set('classifier')
archiveVersion.set('1.0')
manifest {
attributes 'Main-Class': 'Main'
}
}
// ③ Disable the default jar task
jar.enabled = false
// ④ Execute the shadowJar task when compiling
build.dependsOn(shadowJar)
Execute the command gradle build, the jar file will be generated:
<Project Directory>/build/libs/baseName-1.0-classifier.jar
For those who have trouble with the accepted solution, there is another way to exclude resource from shaded jar with DontIncludeResourceTransformer:
https://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#DontIncludeResourceTransformer
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
<resource>BC1024KE.DSA</resource>
</transformer>
</transformers>
From Shade 3.0, this transformer accepts a list of resources. Before that you just need to use multiple transformer each with one resource.
This happened to me in Intellij when I clicked "Add as a Maven Project" on bottom line when Intellij said "non-managed pom files found.". Meanwhile out folder was already generated. So it did not get recent changes.
Deleting out folder and running the program solved the issue for me. out folder was then recreated.
See the answer of Little Fox as well. The error I received was very similar to his.
For someone who using kotlin script(kts) as building script:
task("fatJar", type = Jar::class) {
baseName = "${project.name}-fat"
manifest {
attributes["Implementation-Title"] = "Watcher Jar File"
attributes["Implementation-Version"] = version
attributes["Main-Class"] = "MainKt"
}
from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) {
exclude(listOf("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA"))
}
with(tasks.jar.get() as CopySpec)
}
I had a similar problem. The reason was that I was compiling using a JDK with a different JRE than the default one in my Windows box.
Using the correct java.exe solved my problem.
If you're getting this when trying to bind JAR files for a Xamarin.Android bindings project like so:
JARTOXML : warning J2XA006: missing class error was raised while reflecting com.your.class : Invalid signature file digest for Manifest main attributes
Just open the JAR files using Winzip and delete the meta-inf directories. Rebuild - job done
In Spring Boot, you can do the following:
src/main/resources/META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.AConfiguration,\
org.springframework.boot.autoconfigure.admin.BConfiguration,\
org.springframework.boot.autoconfigure.admin.CConfiguration,\
org.springframework.boot.autoconfigure.admin.DConfiguration,\
org.springframework.boot.autoconfigure.admin.EConfiguration,\
org.springframework.boot.autoconfigure.admin.FConfiguration,\
Which is very nice. However after a year of development the list of auto configuration is now > 15 lines, which makes it hard to manage.
Would like to know if it is possible to separate the spring.factories into multiple files? Preferably would like to keep the whole project in one JAR.
Or maybe there is another ways to help organize the EnableAutoConfiguration that I am not aware of?
Thanks in advance!
While using spring-boot we use multiple "starters", each with an auto-configuration and spring.factories file.
So, one way could be to split your project into modules - one for each auto-configuration, define a dedicated spring.factories file in the module, and import all the modules as a runtime dependency in the main application module.
You can use maven or gradle to manage the multi-module project and the dependencies among them:
Gradle: https://guides.gradle.org/creating-multi-project-builds/
Maven: https://www.baeldung.com/maven-multi-module
Example:
root
moduleA
src/main/resources/META-INF/spring.factories
moduleB
src/main/resources/META-INF/spring.factories
and so on...
I have found a solution for this question.
Note: This exact solution assume that you only used EnableAutoConfiguration in your spring.factiores, it would crash if you use more than one type of config inside spring.factories.
One can do:
src/main/resources/META-INF/spring.factories
src/main/resources/META-INF/spring-2.factories
src/main/resources/META-INF/spring-3.factories
src/main/resources/META-INF/spring-4.factories
and merge this into one file.
Note, I am using Maven Antrun but I suspect Gradle would also have a similar feature.
In your pom.xml, add the following:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>default-ci</id>
<goals>
<goal>run</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<target>
<replace token='org.springframework.boot.autoconfigure.EnableAutoConfiguration=' value=','
dir="${project.build.directory}/classes/META-INF">
<include name="spring-*.factories"/>
</replace>
<concat destfile="${project.build.directory}/classes/META-INF/spring.factories" overwrite="yes" append="yes">
<fileset dir="${project.build.directory}/classes/META-INF" includes="spring-*.factories" />
</concat>
</target>
</configuration>
</execution>
</executions>
</plugin>
And in spring.factories is the normal config:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.AConfiguration,\
org.springframework.boot.autoconfigure.admin.BConfiguration
But in spring-2.factories and others, you start with ,\ instead of the default statement:
spring-2.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.CConfiguration
spring-3.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.DConfiguration
After all that, the outcome spring.factories in your output class directories will be a very nice:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.AConfiguration,\
org.springframework.boot.autoconfigure.admin.BConfiguration,\
org.springframework.boot.autoconfigure.admin.CConfiguration,\
org.springframework.boot.autoconfigure.admin.DConfiguration
I have a maven-multi project, when I create a new eclipse project from it (by M2E 1.0 "Checkout Maven Project from SCM) I want that the eclipse checkstyle plugin is configured for that project automatically.
So I added the maven-eclipse-plugin in parent pom's <pluginManagement> section and configured it to generate .checkstyle file as well as the additional project nature CheckstyleNature. In the modul poms I added the name of the maven-eclipse-plugin in the build section. But when I checkout the project nothing happend, the file is not generated and the nature is not added.
So I think I am doing something completely wrong, but how is it done correct?
Parent pom - plugin management section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.8</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<wtpversion>2.0</wtpversion>
<additionalBuildcommands>
<buildCommand>
<name>org.eclipse.ajdt.core.ajbuilder</name>
<arguments>
<aspectPath>org.springframework.aspects</aspectPath>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.core.springbuilder</name>
</buildCommand>
</additionalBuildcommands>
<additionalProjectnatures>
<projectnature>org.eclipse.ajdt.ui.ajnature</projectnature>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
<projectnature>com.atlassw.tools.eclipse.checkstyle.CheckstyleNature</projectnature>
</additionalProjectnatures>
<additionalConfig>
<file>
<name>.checkstyle</name>
<content>
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
<fileset name="all" enabled="true" check-config-name="My Checkstyle rules" local="false">
<file-match-pattern match-pattern="." include-pattern="true"/>
</fileset>
<filter name="FilesFromPackage" enabled="true">
<filter-data value="target" />
<filter-data value="src/main/resources"/>
<filter-data value="src/test/java"/>
<filter-data value="src/test/resources"/>
<filter-data value="src/main/webapp" />
</filter>
</fileset-config>
]]>
</content>
</file>
</additionalConfig>
</configuration>
</plugin>
Module pom - plugins section:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
</plugin>
There are detailed answers to this topic in Can I Configure m2eclipse through pom.xml?:
Completely automatic configuration of the Eclipse Checkstyle Plugin can only be achieved with a ProjectConfigurator, e.g. m2e-code-quality or m2e-extensions.
For m2e as of version 1.0, you can install them via the m2e marketplace under Preferences->Maven->Discovery->"Open Catalog". For details see the bug tracking for integration of m2e-code-quality into the m2e marketplace.
There is a also solution based on AntRun and XMLTask even for FindBugs and Sonar. It needs manual triggering only once after checkout.
The maven eclipse plugin is not the same thing as the m2e plugin for eclipse, which I'm assuming you are trying to use. Basically you shouldn't use both at the same time.
You can use mvn eclipse:eclipse from the command line to generate project files and then you can import the projects into eclipse. M2e works very differently and instead uses the pom files when you import projects as maven plugins. Probably what you want is to configure the checkstyle plugin and hopefully eclipse would pick up the settings. Same for findbugs and other maven plugins.
However, I actually prefer using mvn eclipse:eclipse and haven't actually verified the above works as expected. M2e is just too much of a time waster for me and seems to go off and do the wrong things frequently. I particularly hate how it has a habit of basically rebuilding everything after command line interaction with maven. But lots of people seem to like m2e.
One must install the "Checkstyle m2e" connector
applies configuration form the maven-checkstyle-plugin to the eclipse checkstyle Plugin
Under window\preferences\Maven\Discover\Open Catalog
And of course one has to change the pom, so that the check style plugin is configured, instead of the eclipse plugin.
Unfortunately it does not working for me! (I will not delete the answer because it may work for somebody else.)
I have a maven plugin that should run in the compile phase, so in the project that consumes my plugin, I have to do something like this:
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>my-goal</goal>
</goals>
</execution>
</executions>
What I need is to by default attach my-goal to the compile phase if the user has included my plugin already (ideally the above part wouldn't be necessary, just the plugin declaration).
Is this possible?
Put an #phase annotation in your Mojo classdef annotations.
The doc says:
#phase <phaseName>
This annotation specifies the default phase for this goal. If you add an execution for this goal to a pom.xml and do not specify the phase, Maven will bind the goal to the phase specified in this annotation by default.
If this doesn't work, I guess a JIRA is warranted.
Create an instance of src\main\resources\META-INF\plexus\components.xml in your plugin.
In there create a LifeCycle mapping for the artifact types that your want your Mojo to support. Make sure that it lists all the phases and plugins you want to support. Probably best to copy from the one from maven-core.jar.
Then add your plugin in to the appropriate LifeCycle(s) at the phase at which you want them built.
Eg the consume-aar Mojo added into the compile phase of the aar lifecycle.
<!-- Android archive (aar) support -->
<component>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<role-hint>aar</role-hint>
<implementation>
org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping
</implementation>
<configuration>
<phases>
<generate-sources>
com.jayway.maven.plugins.android.generation2:android-maven-plugin:generate-sources
</generate-sources>
<process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
<compile>
com.jayway.maven.plugins.android.generation2:android-maven-plugin:consume-aar,
org.apache.maven.plugins:maven-compiler-plugin:compile
</compile>
This is possible, but it is an undocumented maven feature.
Use this components.xml:
<component-set>
<components>
<component>
<role>org.apache.maven.lifecycle.Lifecycle</role>
<implementation>org.apache.maven.lifecycle.Lifecycle</implementation>
<role-hint>myplugin</role-hint>
<configuration>
<id>accurest</id>
<phases>
<phase>my-plugin-not-used-phase</phase>
</phases>
<default-phases>
<compile>
my.package:my-plugin:${project.version}:my-goal
</compile>
</default-phases>
</configuration>
</component>
</components>
but your plugin need to be added with <extensions>true</extensions> to modify existing lifecycle.
More: How to bind plugin mojos (goals) to few phases of default lifecycle?
Real project: https://github.com/spring-cloud/spring-cloud-contract/blob/master/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/resources/META-INF/plexus/components.xml
You associate plugin to maven lifecyle goal. The plugin configuration should be declared in phase.
For example if you wan to run some plugin during build phase you'll need to do something like this :
<project>
...
...
<build>
<plugin>
**Configuration of plugin**
</plugin>
</build>
</project>
Please read carefully about maven lifecycles here (it is fundamental for understanding of maven):
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
And then read about how to configure a plugin : http://maven.apache.org/guides/mini/guide-configuring-plugins.html
P.S. Getting into logic of maven is not easy at the beginning. But it is rewarding afterwards.
My java program is packaged in a jar file and makes use of an external jar library, bouncy castle. My code compiles fine, but running the jar leads to the following error:
Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
I've googled for over an hour searching for an explanation and found very little of value. If anyone has seen this error before and could offer some help, I would be obliged.
For those who got this error when trying to create a shaded uber-jar with maven-shade-plugin, the solution is to exclude manifest signature files by adding the following lines to the plugin configuration:
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<!-- Additional configuration. -->
</configuration>
For those using gradle and trying to create and use a fat jar, the following syntax might help.
jar {
doFirst {
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}
Please use the following command
zip -d yourjar.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*.DSA'
Some of your dependencies are likely signed jarfiles. When you combine them all into one big jarfile, the corresponding signature files are still present, and no longer match the "big combined" jarfile, so the runtime halts thinking the jar file has been tampered with (which it...has so to speak).
Assuming you're using ant, you can solve the problem by eliminating the signature files from your jarfile dependencies. Unfortunately, it's not possible to do this in one step in ant.
However, I was able to get this working with Ant in two steps, without specifically naming each jarfile dependency, by using:
<target name="jar" depends="compile" description="Create one big jarfile.">
<jar jarfile="${output.dir}/deps.jar">
<zipgroupfileset dir="jars">
<include name="**/*.jar" />
</zipgroupfileset>
</jar>
<sleep seconds="1" />
<jar jarfile="${output.dir}/myjar.jar" basedir="${classes.dir}">
<zipfileset src="${output.dir}/deps.jar" excludes="META-INF/*.SF" />
<manifest>
<attribute name="Main-Class" value="com.mycompany.MyMain" />
</manifest>
</jar>
</target>
The sleep element is supposed to prevent errors about files with modification dates in the future.
Other variations I found in the linked threads didn't work for me.
The solution listed here might provide a pointer.
Invalid signature file digest for Manifest main attributes
Bottom line :
It's probably best to keep the official jar as
is and just add it as a dependency in the manifest file for your
application jar file.
Security is already a tough topic, but I'm disappointed to see the most popular solution is to delete the security signatures. JCE requires these signatures. Maven shade explodes the BouncyCastle jar file which puts the signatures into META-INF, but the BouncyCastle signatures aren't valid for a new, uber-jar (only for the BC jar), and that's what causes the Invalid signature error in this thread.
Yes, excluding or deleting the signatures as suggested by #ruhsuzbaykus does indeed make the original error go away, but it can also lead to new, cryptic errors:
java.security.NoSuchAlgorithmException: PBEWithSHA256And256BitAES-CBC-BC SecretKeyFactory not available
By explicitly specifying where to find the algorithm like this:
SecretKeyFactory.getInstance("PBEWithSHA256And256BitAES-CBC-BC","BC");
I was able to get a different error:
java.security.NoSuchProviderException: JCE cannot authenticate the provider BC
JCE can't authenticate the provider because we've deleted the cryptographic signatures by following the suggestion elsewhere in this same thread.
The solution I found was the executable packer plugin that uses a jar-in-jar approach to preserve the BouncyCastle signature in a single, executable jar.
UPDATE:
Another way to do this (the correct way?) is to use Maven Jar signer. This allows you to keep using Maven shade without getting security errors. HOWEVER, you must have a code signing certificate (Oracle suggests searching for "Java Code Signing Certificate"). The POM config looks like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<filters>
<filter>
<artifact>org.bouncycastle:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>your.class.here</mainClass>
</transformer>
</transformers>
<shadedArtifactAttached>true</shadedArtifactAttached>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jarsigner-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>sign</id>
<goals>
<goal>sign</goal>
</goals>
</execution>
<execution>
<id>verify</id>
<goals>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<keystore>/path/to/myKeystore</keystore>
<alias>myfirstkey</alias>
<storepass>111111</storepass>
<keypass>111111</keypass>
</configuration>
</plugin>
No, there's no way to get JCE to recognize a self-signed cert, so if you need to preserve the BouncyCastle certs, you have to either use the jar-in-jar plugin or get a JCE cert.
I had this problem when using IntelliJ IDEA 14.01.
I was able to fix it by:
File->Project Structure->Add New (Artifacts)->jar->From Modules With Dependencies on the Create Jar From Module Window:
Select you main class
JAR File from Libraries
Select copy to the output directory and link via manifest
I faced the same issue, after reference somewhere, it worked as below changing:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<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>
</configuration>
</execution>
</executions>
</plugin>
Assuming you build your jar file with ant, you can just instruct ant to leave out the META-INF dir. This is a simplified version of my ant target:
<jar destfile="app.jar" basedir="${classes.dir}">
<zipfileset excludes="META-INF/**/*" src="${lib.dir}/bcprov-jdk16-145.jar"></zipfileset>
<manifest>
<attribute name="Main-Class" value="app.Main"/>
</manifest>
</jar>
I've recently started using IntelliJ on my projects. However, some of my colleagues still use Eclipse on the same projects. Today, I've got the very same error after executing the jar-file created by my IntelliJ. While all the solutions in here talking about almost the same thing, none of them worked for me easily (possibly because I don't use ANT, maven build gave me other errors which referred me to http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException, and also I couldn't figure out what are the signed jars by myself!)
Finally, this helped me
zip -d demoSampler.jar 'META-INF/*.SF' 'META-INF/*.RSA' 'META-INF/*SF'
Guess what's been removed from my jar file?!
deleting: META-INF/ECLIPSE_.SF
deleting: META-INF/ECLIPSE_.RSA
It seems that the issue was relevant to some eclipse-relevant files.
I had the same issue in gradle when creating a fat Jar; updating the build.gradle file with an exclude line corrected the problem.
jar {
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
manifest {
attributes 'Main-Class': 'com.test.Main'
}
}
In case you're using gradle, here is a full farJar task:
version = '1.0'
//create a single Jar with all dependencies
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version,
'Main-Class': 'com.example.main'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
with jar
}
Compare the folder META-INF in new jar with old jar (before you added new libraries). It is possibility that there will be new files. If yes, you can remove them. It should helps.
Regards,
999michal
A strategy would consist in using ANT to simplify the removal of the signature from each Jar file. It would proceed with the following steps:
Copying the MANIFEST.MF in a temporary file
Removing the Name and SHA entries from the temporary file
Creating a temporary Jar file with the temporary manifest
Removing the temporary manifest
Swapping the original Jar file with the temporary one
Here is an ANT macrodef doing the work:
<macrodef name="unsignjar" description="To unsign a specific Jar file">
<attribute name="jarfile"
description="The jar file to unsign" />
<sequential>
<!-- Copying to the temporary manifest file -->
<copy toFile="#{jarFile}_MANIFEST.tmp">
<resources>
<zipentry zipfile="#{jarFile}" name="META-INF/MANIFEST.MF"/>
</resources>
</copy>
<!-- Removing the Name and SHA entries from the temporary file -->
<replaceregexp file="#{jarFile}_MANIFEST.tmp" match="\nName:(.+?)\nSH" replace="SH" flags="gis" byline="false"/>
<replaceregexp file="#{jarFile}_MANIFEST.tmp" match="SHA(.*)" replace="" flags="gis" byline="false"/>
<!-- Creating a temporary Jar file with the temporary manifest -->
<jar jarfile="#{jarFile}.tmp"
manifest="#{jarFile}_MANIFEST.tmp">
<zipfileset src="#{jarFile}">
<include name="**"/>
<exclude name="META-INF/*.SF"/>
<exclude name="META-INF/*.DSA"/>
<exclude name="META-INF/*.RSA"/>
</zipfileset>
</jar>
<!-- Removing the temporary manifest -->
<delete file="#{jarFile}_MANIFEST.tmp" />
<!-- Swapping the original Jar file with the temporary one -->
<move file="#{jarFile}.tmp"
tofile="#{jarFile}"
overwrite="true" />
</sequential>
`
The definition can then be called this way in an ANT task:
<target name="unsignJar">
<unsignjar jarFile="org.test.myjartounsign.jar" />
</target>
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:314)
at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:268)
at java.util.jar.JarVerifier.processEntry(JarVerifier.java:316)
at java.util.jar.JarVerifier.update(JarVerifier.java:228)
at java.util.jar.JarFile.initializeVerifier(JarFile.java:383)
at java.util.jar.JarFile.getInputStream(JarFile.java:450)
at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:977)
at sun.misc.Resource.cachedInputStream(Resource.java:77)
at sun.misc.Resource.getByteBuffer(Resource.java:160)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:454)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
What helped me (IntelliJ IDEA 2016.3):
File -> Project Structure -> Artifacts -> Add JAR -> Select Main Class -> Choose "copy to the output directory and link via manifest" -> OK -> Apply -> Build -> Build Artifacts... -> Build
It's possible that two different signers mess up java mind.
Try removing META-INF folder from jar, adding manifest and signing JAR again, it helped me: http://jehy.ru/articles/2013/12/13/invalid-signature-file-digest-for-manifest-main-attributes/
If you are looking for a Fat JAR solution without unpacking or tampering with the original libraries but with a special JAR classloader, take a look at my project here.
Disclaimer: I did not write the code, just package it and publish it on Maven Central and describe in my read-me how to use it.
I personally use it for creating runnable uber JARs containing BouncyCastle dependencies. Maybe it is useful for you, too.
You can use Shadow to generate a jar.
Shadow is a Gradle plugin for combining a project's dependency classes and resources into a single output Jar. The combined Jar is often referred to a fat-jar or uber-jar.
Modify build.gradle
plugins {
...
// ① Add the shadow plugin
id "com.github.johnrengelman.shadow" version "5.2.0"
}
...
// ② Config the shadow jar, its name is baseName-1.0-classifier.jar
shadowJar {
archiveBaseName.set('baseName')
archiveClassifier.set('classifier')
archiveVersion.set('1.0')
manifest {
attributes 'Main-Class': 'Main'
}
}
// ③ Disable the default jar task
jar.enabled = false
// ④ Execute the shadowJar task when compiling
build.dependsOn(shadowJar)
Execute the command gradle build, the jar file will be generated:
<Project Directory>/build/libs/baseName-1.0-classifier.jar
For those who have trouble with the accepted solution, there is another way to exclude resource from shaded jar with DontIncludeResourceTransformer:
https://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#DontIncludeResourceTransformer
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
<resource>BC1024KE.DSA</resource>
</transformer>
</transformers>
From Shade 3.0, this transformer accepts a list of resources. Before that you just need to use multiple transformer each with one resource.
This happened to me in Intellij when I clicked "Add as a Maven Project" on bottom line when Intellij said "non-managed pom files found.". Meanwhile out folder was already generated. So it did not get recent changes.
Deleting out folder and running the program solved the issue for me. out folder was then recreated.
See the answer of Little Fox as well. The error I received was very similar to his.
For someone who using kotlin script(kts) as building script:
task("fatJar", type = Jar::class) {
baseName = "${project.name}-fat"
manifest {
attributes["Implementation-Title"] = "Watcher Jar File"
attributes["Implementation-Version"] = version
attributes["Main-Class"] = "MainKt"
}
from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) {
exclude(listOf("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA"))
}
with(tasks.jar.get() as CopySpec)
}
I had a similar problem. The reason was that I was compiling using a JDK with a different JRE than the default one in my Windows box.
Using the correct java.exe solved my problem.
If you're getting this when trying to bind JAR files for a Xamarin.Android bindings project like so:
JARTOXML : warning J2XA006: missing class error was raised while reflecting com.your.class : Invalid signature file digest for Manifest main attributes
Just open the JAR files using Winzip and delete the meta-inf directories. Rebuild - job done