Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add sqljdbc_auth.dll to my maven project

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]
like image 892
Kadymov Mukhammed Avatar asked Dec 06 '25 03:12

Kadymov Mukhammed


1 Answers

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:

  1. Have the dlls stored in your application path. For instance:
project_root
├─src (or any other source path structure)
│ └─...packages...
└─extlib
  └─SqlJdbc
    └─auth
      ├─x64
      │ └─sqljdbc_auth.dll
      └─x86
        └─sqljdbc_auth.dll
  1. Use the following static initialization code in the class that makes JDBC connection (java <= 11 version):
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

  1. Deploy the directory containing dlls (i.e. 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.

like image 133
julien.giband Avatar answered Dec 07 '25 19:12

julien.giband



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!