Kürzlich habe ich einen Verbindungschecker für das leistungsstarke Remote-Execution-Framework Overthere von Deployit vorbereitet. Um den Checker so kompakt wie möglich zu machen, habe ich ein
Doppelt sehen
TrueZIP verwendet eine de.schlichtherle.truezip.fs.spi.FsDriverService Provider-Konfigurationsdatei in META-INF/services, um Treiber für verschiedene Archivformate zu registrieren. Der Checker schlug fehl, weil einer der erforderlichen Treiber nicht geladen wurde, obwohl der Code korrekt im jar-with-deps enthalten war. Die Option duplicate von Ant's Jartask3 und Gradle issue 1050, in dem es um das Zusammenführen von Dateien bei der Erstellung von Archiven geht, geben einen Hinweis auf das Problem: Nach dem Verpacken in ein einziges jar-with-deps-Archiv wurde nur eine der TrueZIP Provider-Konfigurationsdateien gefunden.
Maven, Gradle und Java
Als ich das vonMaven4 erstellte jar-with-deps untersuchte, war ziemlich klar, warum: das JAR enthält nur eine der Konfigurationsdateien - in meinem Fall scheint es die erste zu sein, aber das kann auch unbestimmt sein. Vermutlich geschieht dies, weil Maven ein temporäres Verzeichnis verwendet, um den Inhalt des Archivs vorzubereiten, das natürlich nicht mehrere Dateien mit demselben Namen enthalten kann. MitGradle5 sind die Dinge etwas interessanter, denn das Archiv enthält tatsächlich alle Konfigurationsdateien - das ZIP-Format unterstützt doppelte Einträge6. Allerdings spielt ClassLoader.getResources nicht mit, so dass wieder nur ein Eintrag gefunden wird.
Es kann nur einen geben
Im Grunde genommen scheint das Zusammenführen der betroffenen Dateien die einzige Möglichkeit zu sein, dieses Problem zu umgehen. Hier ist ein mögliches Gradle Snippet7: [groovy] task jarWithDeps(type: Jar, dependsOn: classes) { mergeDir = "${buildDir}/merge" // In einem Projekt mit mehreren Modulen, in dem Deps vererbt werden, könnte eine Lazy Var erforderlich sein runtimeDeps = configurations.runtime.collect { zipTree(it) } doFirst { new File(mergeDir).delete() mergeFiles(mergeDir, runtimeDeps, file-to-merge) // ... möglicherweise auch andere Dateien } // die Klassen dieses Projekts und alle Deps von sourceSets.classesDir from(runtimeDeps) { exclude file-to-merge } from mergeDir } private def mergeFiles(targetDir, fileTrees, relativePath) { // Vorbereitung der Zusammenführung mergedFile = new File("${targetDir}/${relativePath}") new File(mergedFile.parent).mkdirs() fileTrees.matching({ include "*/${relativePath}" }).each { fusionierteDatei << it.bytes } } [/groovy] Leider habe ich keine ähnliche Option für den Maven Archiver finden können, aber ich schätze, dass es da draußen im Maven-Ökosystem etwas geben muss ;-) Geändert am 21/07/2011 um hinzuzufügen: Der Beispielcode enthält jetzt mögliche Lösungen, die in den Kommentaren vorgeschlagen werden. Führen Sie gradle clean jarWithDeps2, mvn clean package -Pwith-shade-plugin oder mvn clean package-Pwith-keystone-plugin8 aus, um sie auszuprobieren. Geändert am 25/07/2011 um hinzuzufügen: Sie können jetzt auch mvn clean package -Pwith-services-handler ausführen, um zu sehen, wie das Assembly-Plugin die <containerDescriptorHandlers> sich auch darum kümmern können.
- Auch bekannt als "farJar". Eine entsprechende Gradle-Aufgabendefinition finden Sie hier.
- Siehe MultiSPI für einen Ansatz, der mehr Flexibilität und "moderne Alternativen" für Dienstanbieter bietet.
- Beachten Sie, dass das jar-Dienstprogramm selbst keine ähnliche Option bietet.
- mvn clean Paket ausführen
- gradle clean jarWithDeps ausführen
- obwohl der ZipOutputStream offensichtlich nicht sehr glücklich damit war und, der Implementierung von 1.6.0_20 nach zu urteilen, immer noch eine ZipException auslöst
- Es wäre interessant zu versuchen, die Zusammenführung zur Zeit der JAR-Erstellung durchzuführen, vielleicht indem man "merge-so-far(s)" im mergeDir behält und mit eachFile die nicht zusammengeführten Dateien ersetzt und gleichzeitig die "merge-so-far(s)" aktualisiert.
- erforderte zwei Korrekturen des Codes, damit er auf meinem System korrekt funktioniert
Verfasst von
Andrew Phillips
Contact