I am trying to establish connection to a database. It's a simple project with using maven.
I have problems with sqljdbc_auth.dll
I have added mssql jdbc driver and added a dependency in pom.xml
<dependency>
<groupId>com.microsoft</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>4.0.0</version>
</dependency>
This is my try block
try {
// Establish the connection.
SQLServerDataSource ds = new SQLServerDataSource();
ds.setIntegratedSecurity(true);
ds.setServerName("BUILDSRV");
ds.setDatabaseName("master");
ds.setIntegratedSecurity(true);
con = ds.getConnection();
}
and I get this error
21.11.2012 18:07:04 com.microsoft.sqlserver.jdbc.AuthenticationJNI <clinit>
WARNING: Failed to load the sqljdbc_auth.dll cause :- no sqljdbc_auth in java.library.path
com.microsoft.sqlserver.jdbc.SQLServerException:
I have my sqljdbc_auth.dll but I don't need to put it to my C:\windows\...
I need to add it in my project from maven. How can I do this?
I tried to add it to the pom.xml but it doesn't work
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>attach-artifacts</id>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<file>target</file>
<type>dll</type>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
I got another error while building
Failed to execute goal org.codehaus.mojo:build-helper-maven-plugin:1.1:attach-artifact (attach-artifacts) on project mavenproject1dbconnect: Unable to parse configuration of mojo org.codehaus.mojo:build-helper-maven-plugin:1.1:attach-artifact for parameter file: Cannot configure instance of org.codehaus.mojo.buildhelper.Artifact from target -> [Help 1]
Based on information found in this answer, you could do it by injecting the dll into java.library.path at runtime.
I've had this running in production for a few years now with no problem on Java <= 8. Never really used with newer versions though. Quick tests worked with Java 11, not Java 15
Here's how I'm doing it:
project_root
├─src (or any other source path structure)
│ └─...packages...
└─extlib
└─SqlJdbc
└─auth
├─x64
│ └─sqljdbc_auth.dll
└─x86
└─sqljdbc_auth.dll
static {
File file;
if ("64".equals(System.getProperty("sun.arch.data.model")))
file = new File("./extlib/SqlJdbc/auth/x64");
else
file = new File("./extlib/SqlJdbc/auth/x86");
String dllPath;
try {
dllPath = file.getCanonicalPath();
synchronized(Runtime.getRuntime()) {
final Field usrPathsField = ClassLoader.class.getDeclaredField("usr_paths");
usrPathsField.setAccessible(true);
Object o = usrPathsField.get(null);
String[] paths = o == null ? new String[0] : (String[]) o;
if (!Arrays.stream(paths).anyMatch(s -> dllPath.equals(s))) {
String[] usr_paths = Arrays.copyOf(paths, paths.length + 1);
usr_paths[paths.length] = file.getCanonicalPath();
usrPathsField.set(null, usr_paths);
}
}
DriverManager.registerDriver(new SQLServerDriver());
} catch (Exception e) {
e.printStackTrace();
throw new ExceptionInInitializerError(e);
}
}
According to this answer, you should be able to push it to at least Java <= 13 using MethodHandles.privateLookupIn instead of ClassLoader.class.getDeclaredField. For instance:
Lookup cl = MethodHandles.privateLookupIn(ClassLoader.class, MethodHandles.lookup());
VarHandle usrPathsField= cl.findStaticVarHandle(ClassLoader.class, "usr_paths", String[].class);
Object o = usrPathsField.get();
...
usrPathsField.set(usr_paths);
It's definitely broken with Java 15, as field usr_paths doesn't exist anymore in ClassLoader
At this point, you should be able to run your code from IDE
extlib) alongside your jar. For Maven, you can use the following in pom.xml:<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/extlib</outputDirectory>
<resources>
<resource>
<directory>extlib</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
From there, if you need your dlls packed inside your jar, you can do so using maven-resources-plugin, and unpack the required dll at runtime, and then force it onto the library path using a variation of above code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With