2

I have a Java application that needs to run as a Windows service. The application needs to connect to Microsoft SQL server using Integrated Security. This means that Java needs to have the location of the driver dll in the java library path.

According to the prunsrv documentation, it is possible to pass in JVM options using the following parameter:

++JvmOptions="-Djava.library.path=drivers/MS SQL/x64"

where the path above is specific to my case.

When running the application using java.exe from a command line, and passing in the same library path as above (with the appropriate java syntax), it works exactly as expected. However, when running the application as a service (using jvm mode in prunsrv) it gives the following exception and does not connect:

com.microsoft.sqlserver.jdbc.SQLServerException: 
This driver is not configured for integrated authentication. com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(SQLServerConnection.java:1667)
...
Caused by: java.lang.UnsatisfiedLinkError: no sqljdbc_auth in java.library.path
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1865)
...

The exception is the same as when the "-Djava.library.path=drivers/MS SQL/x64" options is left out from the console application. It seems like the service is not setting the library path as expected.

Upon reviewing the documentation for prunsrv there is an option that looks promising:

--LibraryPath : Directory added to the search path used to locate the DLLs for the JVM. This directory is added both in front of the PATH environment variable and as a parameter to the SetDLLDirectory function.

This is exactly what I want.

Sadly, when setting this option along with the java.library.path jvm option, it still throws the exact same exception as before. It's as if it hasn't applied the setting.

Luke Machowski
  • 3,983
  • 2
  • 31
  • 28

1 Answers1

2

I am posting this answer because I found it really difficult to find documentation on this particular use case. I hope This post will save someone some time.

It turns out that the solution for jvm mode is to use the --LibraryPath option BUT you must NOT include the same library path in the ++JvmOptions="..." because then it seems to break it and you get the exception.

In summary...

  1. Keep whatever jvm options you normally need in the ++JvmOptions parameter.
  2. REMOVE all java.library.path configurations from the ++JvmOptions parameter. NB!
  3. Add another --LibraryPath parameter with the paths removed in step 1.

As in:

++JvmOptions="-Dfile.encoding=UTF8;-Xmx6g" --LibraryPath="%solutionRootPath%\bin\drivers\MS SQL\x64"

where the path and environment variable above is specific to my use case.

After doing this, the solution works the same was as if it was run from the command line using java.exe.

Luke Machowski
  • 3,983
  • 2
  • 31
  • 28
  • 1
    I found that when I provide --LibraryPath, it does not operate as the documentation states. The docs say the path provided here will be prepended to the system PATH variable. However, my experience was that it totally overwrites the system PATH. I had to use `--LibraryPath="%MYPATH%\lib;%PATH%"`. My application calls some system processes such as `reg` and these would no longer resolve without appending `%PATH%`. – Aaron St. Clair Jul 27 '21 at 22:03