I have the following build.gradle in my project
plugins {
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'com.oracle.database.jdbc:ojdbc11-production:21.3.0.0'
implementation 'com.microsoft.sqlserver:mssql-jdbc:9.4.0.jre8'
}
tasks.named('jar') {
setDuplicatesStrategy(DuplicatesStrategy.WARN)
manifest {
attributes 'Main-Class': 'com.example.App'
}
from {
configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
File META-INF/services/java.sql.Driver
is present in both of imported jars. Actually this Oracle JDBC dependency imports multiple jars and they have more conflicting files (with differing contents) among themselves (e.g. META-INF/native-image/native-image.properties
and others in this directory).
when DuplicatesStrategy is set to WARN, the Oracle driver overwrites SQL Server JDBC driver's META-INF/services/java.sql.Driver
. What are the consequences of this (and others) file being overwritten?
How should I handle these duplicate files? Is there any way to have all files from all jars? The chance of jar getting some of its files overwritten makes me feel uneasy.
Are conflicting files common?
CodePudding user response:
Consider not building a fatjar. Otherwise, you will need to merge META-INF/services/java.sql.Driver
from the various drivers into a single file (either automatically, or provide your own). If you do not merge, automatic driver loading will not work for the driver(s) whose service definition file was not included. If you cannot or do not want to merge (or provide your own version), you will need to resort to explicitly loading drivers using Class.forName
. See also How is driver class located in JDBC4.
As to the DuplicateStrategy
to use, it is probably best to use FAIL
and explicitly exclude files or locations, or come up with a strategy to merge them, but this might be cumbersome.
As to the other files, I cannot really answer, but META-INF/native-image/*
seems to be related to using the library in GraalVM, so unless you're using that, you can probably safely ignore files in that directory.
However, if this really concerns you, or you don't know what files do, the better option is to not use fatjars (a.k.a uberjars), and instead use a way of deployment that correctly generates a class-path (e.g. using the manifest, or a launcher file) and keeps the various libraries used by your application separate. For example, see Add classpath in manifest using Gradle.