web-dev-qa-db-fra.com

Fichier JAR invalide ou corrompu créé par le plugin d'ombrage Maven

Après avoir ajouté la dépendance Maven jFree à mon application existante, je ne suis pas en mesure d'exécuter le fichier jar créé.

Le seul message d'erreur que je reçois est le suivant:

Java -jar target/com.company.product-1.0.0-SNAPSHOT.jar 
Error: Invalid or corrupt jarfile target/com. company.product-1.0.0-SNAPSHOT.jar

Le pom.xml Complet ressemble à ceci:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.Apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.Apache.org/POM/4.0.0 http://maven.Apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion
<groupId>com.mycompany</groupId>
<artifactId>com.mycompany.test</artifactId>
<name>${project.artifactId}</name>
<version>1.0.0-SNAPSHOT</version>

<properties>
    <Java-version>1.7</Java-version>
    <org.springframework-version>3.1.1.RELEASE</org.springframework-version>
    <org.springframework.data-version>1.0.3.RELEASE</org.springframework.data-version>
    <org.springframework.ws-version>2.0.4.RELEASE</org.springframework.ws-version>
    <org.springframework.ws.oxm-version>1.5.10</org.springframework.ws.oxm-version>
    <org.aspectj-version>1.6.12</org.aspectj-version>
    <org.slf4j-version>1.5.10</org.slf4j-version>
    <Selenium-Java-version>2.25.0</Selenium-Java-version>
    <browser-mob-version>2.0-beta-6</browser-mob-version>
</properties>

<dependencies>

    <!-- Hint A: If we delete this dependency it works -->
    <dependency>
        <groupId>org.jfree</groupId>
        <artifactId>jfreechart</artifactId>
        <version>1.0.14</version>
                    <exclusions>
            <exclusion>
                <artifactId>itext</artifactId>
                <groupId>com.lowagie</groupId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.3.2</version>
    </dependency>

    <dependency>
        <groupId>de.schlichtherle.io</groupId>
        <artifactId>truezip</artifactId>
        <version>6.6</version>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>Apache-log4j-extras</artifactId>
        <version>1.1</version>
    </dependency>

    <!-- Caching with ehcache -->
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>2.5.2</version>
        <type>pom</type>
    </dependency>

    <!-- Spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${org.springframework-version}</version>
        <exclusions>
            <!-- Exclude Commons Logging in favor of SLF4j -->
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-core</artifactId>
        <version>3.0.3.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-web</artifactId>
        <version>3.0.3.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-config</artifactId>
        <version>3.0.3.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${org.springframework-version}</version>
        <scope>test</scope>
    </dependency>
    <!-- Hibernate -->
    <dependency>
        <groupId>org.hibernate.Java-persistence</groupId>
        <artifactId>jpa-api</artifactId>
        <version>2.0-cr-1</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>3.5.1-Final</version>
    </dependency>

    <!-- Database Connectors (HSQL should be removed later) -->
    <dependency>
        <groupId>hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <version>1.8.0.7</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-Java</artifactId>
        <version>5.1.16</version>
    </dependency>

    <!-- AspectJ -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>${org.aspectj-version}</version>
    </dependency>

    <!-- Logging -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${org.slf4j-version}</version>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.16</version>
    </dependency>

    <!-- @Inject -->
    <dependency>
        <groupId>javax.inject</groupId>
        <artifactId>javax.inject</artifactId>
        <version>1</version>
    </dependency>

    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <!-- Spring Data JPA dependencies -->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>${org.springframework.data-version}</version>
    </dependency>
    <dependency>
        <groupId>javax.ws.rs</groupId>
        <artifactId>jsr311-api</artifactId>
        <version>1.1.1</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-oxm</artifactId>
        <version>${org.springframework.ws.oxm-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-xml</artifactId>
        <version>${org.springframework.ws-version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-ws-core</artifactId>
        <version>${org.springframework.ws-version}</version>
    </dependency>
    <dependency>
        <groupId>javax.xml</groupId>
        <artifactId>jaxb-impl</artifactId>
        <version>2.1</version>
    </dependency>
    <dependency>
        <groupId>javax.xml</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.1</version>
    </dependency>

    <!-- Test -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.7</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-all</artifactId>
        <version>1.9.0</version>
        <scope>test</scope>
    </dependency>

    <!-- Common Utils -->
    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>2.6</version>
    </dependency>

    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>

    <dependency>
        <groupId>commons-cli</groupId>
        <artifactId>commons-cli</artifactId>
        <version>1.2</version>
    </dependency>       

    <!-- Selenium -->
    <dependency>
        <groupId>org.seleniumhq.Selenium</groupId>
        <artifactId>Selenium-Java</artifactId>
        <version>${Selenium-Java-version}</version>
    </dependency>

    <dependency>
        <groupId>org.seleniumhq.Selenium</groupId>
        <artifactId>Selenium-firefox-driver</artifactId>
        <version>${Selenium-Java-version}</version>
    </dependency>

    <dependency>
        <groupId>org.seleniumhq.Selenium</groupId>
        <artifactId>Selenium-chrome-driver</artifactId>
        <version>${Selenium-Java-version}</version>
    </dependency>

    <!-- CSV Lib for Keyword Checker -->
    <dependency>
        <groupId>net.sf.opencsv</groupId>
        <artifactId>opencsv</artifactId>
        <version>2.0</version>
    </dependency>

    <!-- Google Places API -->
    <dependency>
        <groupId>com.google.api-client</groupId>
        <artifactId>google-api-client</artifactId>
        <version>1.10.3-beta</version>
        <exclusions>
            <exclusion>
                <artifactId>jackson-core-asl</artifactId>
                <groupId>org.codehaus.jackson</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.google.api-client</groupId>
        <artifactId>google-api-client-appengine</artifactId>
        <version>1.10.3-beta</version>
    </dependency>

    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.9</version>
    </dependency>

    <!-- Google Geocode -->
    <dependency>
        <groupId>com.google.code.geocoder-Java</groupId>
        <artifactId>geocoder-Java</artifactId>
        <version>0.9</version>
    </dependency>

    <dependency>
        <groupId>com.googlecode.json-simple</groupId>
        <artifactId>json-simple</artifactId>
        <version>1.1</version>
    </dependency>

    <dependency>
        <groupId>com.googlecode.json-simple</groupId>
        <artifactId>json-simple</artifactId>
        <version>1.1</version>
    </dependency>

    <dependency>
        <groupId>net.sf.jgrapht</groupId>
        <artifactId>jgrapht</artifactId>
        <version>0.8.3</version>
    </dependency>

    <dependency>
        <groupId>jgraph</groupId>
        <artifactId>jgraph</artifactId>
        <version>5.13.0.0</version>
    </dependency>

    <!-- Apache Http Client -->
    <dependency>
        <groupId>org.Apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.2.1</version>
    </dependency>

    <!-- Amazon web services client -->
    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-Java-sdk</artifactId>
        <version>1.2.15</version>
        <exclusions>
            <exclusion>
                <artifactId>jackson-core-asl</artifactId>
                <groupId>org.codehaus.jackson</groupId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- Docx4j - reading Excel files  -->
    <dependency>
        <groupId>org.docx4j</groupId>
        <artifactId>docx4j</artifactId>
        <version>2.8.0</version>
    </dependency>

    <!-- Browser Mob Proxy -->

    <dependency>
        <groupId>biz.neustar</groupId>
        <artifactId>browsermob-proxy</artifactId>
        <version>${browser-mob-version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.seleniumhq.Selenium</groupId>
                <artifactId>Selenium-api</artifactId>
            </exclusion>
            <exclusion>
                <artifactId>icu4j</artifactId>
                <groupId>com.ibm.icu</groupId>
            </exclusion>
            <exclusion>
                <artifactId>jackson-mapper-asl</artifactId>
                <groupId>org.codehaus.jackson</groupId>
            </exclusion>
            <exclusion>
                <artifactId>jackson-core-asl</artifactId>
                <groupId>org.codehaus.jackson</groupId>
            </exclusion>
            <exclusion>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-jdk14</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <!-- Hint B: If we copy this Apache POI dependencies to the top, it works -->
    <!-- Apache POI - for reading xlsx files -->
    <dependency>
        <groupId>org.Apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.8</version>
    </dependency>

    <dependency>
        <groupId>org.Apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.8</version>
    </dependency>

    <dependency>
        <groupId>org.Apache.xmlbeans</groupId>
        <artifactId>xmlbeans</artifactId>
        <version>2.5.0</version>
    </dependency>

    <dependency>
        <groupId>org.Apache.poi</groupId>
        <artifactId>ooxml-schemas</artifactId>
        <version>1.1</version>
    </dependency>

</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>${Java-version}</source>
                <target>${Java-version}</target>
            </configuration>
        </plugin>

        <plugin>
            <groupId>org.Apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>

                            <!-- must be SURE to do this with both spring.handlers and spring.schemas. 
                                otherwise you won't be able to use them in the spring config files. -->
                            <transformer implementation="org.Apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.handlers</resource>
                            </transformer>

                            <transformer implementation="org.Apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.schemas</resource>
                            </transformer>

                            <transformer implementation="org.Apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.mycompany.test.Start</mainClass>
                            </transformer>
                        </transformers>

                        <filters>
                          <filter>
                            <artifact>bouncycastle:bcprov-jdk15</artifact>
                            <excludes>
                              <exclude>META-INF/BCKEY.DSA</exclude>
                              <exclude>META-INF/BCKEY.SF</exclude>
                              <exclude>META-INF/MANIFEST.MF</exclude>
                            </excludes>
                          </filter>
                        </filters>                          

                    </configuration>
                </execution>
            </executions>
        </plugin>

    </plugins>
</build>

Je n'obtiens aucune autre information de débogage si j'exécute le bocal.

Existe-t-il une option pour valider le fichier jar? Ou avoir quelque chose comme Java -verbose ...?

étapes pour reproduire:

  1. créer un nouveau dossier
  2. Copiez le Pom.xml d'en haut dans le dossier.
  3. Enregistrez le petit `vide principal statique public (...). dans src/main/Java/com/mycompany/test/Start.Java
  4. exécuter mvn clean package
  5. exécuter Java -jar target/com.mycompany.test-1.0.0-SNAPSHOT.jar

Pièce jointe 1:

package com.mycompany.test;


public class Start
{
    public static void main(final String[] args) 
    {
        System.out.println("If you are able to get this printed with Java -jar you made it. Thanks a lot! :)");
    }
}

Modifier 1:

J'ai commencé à supprimer certaines dépendances pour identifier le problème. Mais je n'ai pas une compréhension claire de ce qui ne va pas.

Maintenant, j'ai compris (voir l'indice B dans le pom.xml) que le déplacement des dépendances Apache POI vers le haut résoudra le problème. Mais je ne sais toujours pas pourquoi et quel est le problème.

34
d0x

De mon côté, si je construis votre projet en utilisant le pom.xml vous nous avez montré, avec Apache-poi déclaré après jfreechart, puis comme vous l'avez mentionné, j'obtiens un JAR corrompu. L'échange de l'ordre de ces deux dépendances me donne en effet un JAR correct.

J'ai une expérience antérieure avec le maven-shade-plugin et quand je l'ai utilisé, j'ai eu des problèmes avec le JAR créé META-INF répertoire, donc je l'ai vérifié pour les défauts.

J'ai essayé de copier (à l'aide de Total Commander) le META-INF répertoire quelque part sur mon système de fichiers local et ce que j'ai remarqué, c'est qu'il y a eu des erreurs lors de la copie des fichiers dans META-INF/licences/. Si j'ai essayé de les copier quelque part individuellement et que cela a fonctionné mais je n'ai pas pu copier le tout. Ma conclusion était que l'archive JAR/Zip est corrompue.

Ce que j'ai fait, c'est que j'ai entré ce JAR dans Total Commander (Ctrl+PgDown sur le fichier JAR) et moi renommé thirdpartylicenses.txt à thirdpartylicenses.txt.wtf. En faisant cela, Total Commander vous propose de l'enregistrer et de reconditionner le JAR (j'ai installé le plugin Total7Zip Total Commander packer - si quelqu'un essaie cela et que cela ne fonctionne pas, essayez-le avec celui-ci installé).

Après ça. Ça marche.

(J'ai également essayé de reconditionner le tout sans renommer quoi que ce soit à l'aide des commandes unzip/Zip de Cygwin, mais cela n'a pas fonctionné, la nouvelle archive était toujours corrompue. Total Commander ou le plugin I 'ai mentionné fait de la magie.)

Je suppose que le maven-shade-plugin crée simplement une archive Zip/JAR corrompue ou invalide. Je ne sais pas pourquoi et peut-être que ce que j'ai décrit ne fonctionnera pas pour quelqu'un d'autre, mais j'ai pensé le mentionner afin que je puisse aider.


Je ne pouvais pas laisser ça tranquille, alors j'ai creusé plus profondément et je pense avoir trouvé la réponse.

Le mauvais JAR contient 65608 entrées. Le bon JAR contient 65450 entrées.

Devinez quelle est la limite supérieure de le nombre d'entrées pour un plain fichier Zip ? Ouais. L'article Wiki parle d'un format Zip64 qui surmonte cette limitation.

Le bon JAR a moins d'entrées car les dépendances réelles changent à cause de la position des déclarations de dépendance dans votre pom.xml. ( Comme décrit par cette réponse. )

J'ai compté les entrées comme ça.

Collections.list(new JarFile("...").entries()).size();

J'utilisais Java 7 qui semble prendre en charge le nouveau format Zip64 , donc peut-être que si quelqu'un essaie de compter les entrées dans le mauvais JAR utilisant Java 5 ou 6 recevra une erreur (je ne suis pas sûr cependant).

J'ai également essayé d'exécuter le JAR éclaté . J'ai décompressé l'intégralité du JAR dans un répertoire et exécuté le tout comme ceci.

Java -cp <dir/ com.mycompany.test.Start

A fonctionné comme un charme.


Conclusion. Ne pas abuser du maven-shade-plugin.

J'ai un projet au travail où je construis mon projet comme ça.

  • Je copie les dépendances de mon projet en utilisant maven-dependency-plugin . Vérifiez copy-dependencies objectif . Cela copie vos dépendances dans target/dependency si je me souviens bien.
  • En utilisant le maven-jar-plugin J'ajoute ces dépendances à mon JAR final MANIFEST.MF comme Class-Path entrées utilisant ces options dans la configuration des plugins.

    <classpathPrefix>dependency/</classpathPrefix>
    <addClasspath>true</addClasspath>
    

    Je vais donc avoir Class-Path entrées comme dependency/<artifactId>-<version>.jar, etc.

  • Après cela, j'utilise maven-Assembly-plugin pour créer une distribution Zip contenant mon JAR final et l'ensemble dependency/ dossier.
  • Lorsque je déploie mon application, je peux l'exécuter comme Java -jar final.jar.

J'ai principalement choisi d'utiliser cette solution, car dans mon projet, j'utilise des JAR Bouncy Castle, lesquels ont des extravagants ceci et cela dans leur META-INF répertoire. Quand j'ai utilisé le maven-shade-plugin pour créer mon JAR exécutable final, tout l'enfer s'est déchaîné et je suis devenu méchant cette méthode n'a pas pu être trouvée et cette signature n'est pas tout à fait correcte .

Vous devriez aussi faire quelque chose comme ça. Cette entreprise d'ombrage Maven est trop ombragée pour être utile (jeu de mots voulu).


Voici n article de blog sur tout le processus que j'ai essayé de décrire juste au-dessus (grâce à baba ), peut-être que cela aidera quelqu'un à l'avenir.

45
Kohányi Róbert

L'Iran mvn dependency:tree avec votre configuration et cela donnera une différence lorsque vous déplacez le org.Apache.poi plus haut dans les déclarations de dépendance.

Ceci est extrait de Introduction to the Dependency Mechanism concernant l'ordre des dépendances:

Médiation de dépendance - cela détermine quelle version d'une dépendance sera utilisée lorsque plusieurs versions d'un artefact sont rencontrées. Actuellement, Maven 2.0 prend uniquement en charge l'utilisation de la "définition la plus proche", ce qui signifie qu'il utilisera la version de la dépendance la plus proche de votre projet dans l'arborescence des dépendances. Vous pouvez toujours garantir une version en la déclarant explicitement dans le POM de votre projet. Notez que si deux versions de dépendances sont à la même profondeur dans l'arborescence de dépendances, jusqu'à Maven 2.0.8, il n'était pas défini laquelle gagnerait mais puisque Maven 2.0.9 c'est l'ordre dans le déclaration qui compte: la première déclaration gagne .

Il semble y avoir un conflit dans votre résolution de dépendance et cela provoque votre fichier jar corrompu (je ne sais pas pourquoi il est corrompu).

Quoi qu'il en soit, voici les différences entre les deux poms (à gauche est Origin, à droite est avec org.Apache.poi plus haut):

enter image description hereenter image description here

( Peut-être que c'est difficile à voir sur les photos mais si vous zoomez vous verrez.)

La grande différence est que dans le pom non fonctionnel, le org.Apache.httpcomponents:httpcore:jar:4.2.1 a une dépendance sur commons-codec:commons-codec:jar:1.6, et dans le pom de travail, cette dépendance a été remplacée par commons-codec:commons-codec:jar:1.5.

Je suppose qu'il y a un problème avec le 1.6 version de commons-codec ensemble avec org.Apache.poi:poi:jar:3.8 qui a besoin du 1.5 version.


Modifier

Après cette excellente réponse qui explique pourquoi le fichier jar est corrompu (trop d'entrées dans le jar), je veux juste ajouter une solution simple qui fonctionne au moins pour votre problème particulier.

Ajoutez la balise <minimizeJar>true</minimizeJar> à ton maven-shade-plugin configuration.

Après cela, votre Java -jar target/com.mycompany.test-1.0.0-SNAPSHOT.jar la ligne de commande fonctionnera.

11
maba