How to reference java.sql from a Scala Script without encountering SecurityException?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP



How to reference java.sql from a Scala Script without encountering SecurityException?



Since Java 9, calling objects defined in java.sql from within Scala throw a java.lang.SecurityException when used directly from a scala script.


Java Version: 10.0.1
Scala Version: 2.12.4
sbt Version: 1.2.0



The below screenshot is an entire minimum working example, with console output for a working and non-working version. Specifically: copying the script code into a class, and running it from that class, resolves the issue. Is there a way to write a Scala script that directly uses objects from java.sql?


java.sql



build.sbt


build.sbt


name := "mypackage"
version := "0.1"
scalaVersion := "2.12.4"

libraryDependencies += "org.postgresql" % "postgresql" % "42.2.4"



broken-script.scala


broken-script.scala


import java.sql.Connection, DriverManager
import java.util.Properties

object Main

private def url = "jdbc:postgresql://localhost:5432/postgres"

val credentials: Properties =
val properties = new Properties()
properties.setProperty("user", "integration_test")
properties.setProperty("password", "integration-pass")

properties


def connect(): Connection =
DriverManager.getConnection(url, credentials)


def run(): Unit =
connect()




Main.run()



As shown in the console output below, broken-script.scala encounters a SecurityException.


broken-script.scala



brokenScript.scala Output


brokenScript.scala Output


:load scripts/broken-script.scala
Loading scripts/broken-script.scala...
import java.sql.Connection, DriverManager
import java.util.Properties
defined object Main
java.lang.securityException: Prohibited package name: java.sql
at java.base/java/lang.ClassLoader.preDefineClass(ClassLoader.java:891)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java 1007)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:545)
at java.base/java.net.URLClassLoader.access$100(URLClassLoader.java:83)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:453)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:447)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/net.URLClassLoader.findClass(URLClassLoader.java:446)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:566)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:553)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
at Main$.connect(scripts/broken-script.scala:26)
at Main$.run(scripts/broken-script.scala:30)



src/main/scala/mypackage/Main.scala


src/main/scala/mypackage/Main.scala


package mypackage

import java.sql.Connection, DriverManager
import java.util.Properties

object Main

private def url = "jdbc:postgresql://localhost:5432/postgres"

val credentials: Properties =
val properties = new Properties()
properties.setProperty("user", "integration_test")
properties.setProperty("password", "integration-pass")

properties


def connect(): Connection =
DriverManager.getConnection(url, credentials)


def run(): Unit =
connect()





working-script.scala


working-script.scala


mypackage.Main.run()

println("Success")



An image of the entire project.



enter image description here





Are you using Java 9? See stackoverflow.com/questions/46494112/…
– Rich
Aug 16 at 9:25





@Rich Java 10. Switched to Java 8 and it works perfectly.
– Will Beason
Aug 16 at 13:24




3 Answers
3



This situation with SecurityException looks very weird. I tried to reproduce your issue on my machine, but I didn't face SecurityException despite I followed the described steps.


SecurityException


SecurityException



I used the next code:


import java.sql.DriverManager
import java.util.Properties

object PostgresTest extends App

def connect() =
val properties = new Properties()
properties.setProperty("user", "postgres")
properties.setProperty("password", "admin")

println("Attempt to establish connection ...")

val someMetaData = DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgres", properties)
.getMetaData
.getDefaultTransactionIsolation

println(s"If you see this line, it works fine: $someMetaData")




I tried the different approaches:



with sbt console:
:load /home/username/space/test-project/src/main/scala/PostgresTest.scala
and PostgresTest.connect() - no SecurityException


sbt console


:load /home/username/space/test-project/src/main/scala/PostgresTest.scala


PostgresTest.connect()


SecurityException



sbt console and :paste mode, it works fine


sbt console


:paste


sbt runMain


connect()


IntelliJ



SBT - 1.1.1 and Scala - 2.12.4


SBT - 1.1.1


Scala - 2.12.4



I suggest that can be a problem on IntelliJ side. If any of the scenarios which I described above wouldn't work for you, please, notify me.





For Java 10: (1) :load fails, (2) :paste fails, (3) runMain fails. I'm not sure what (4) is. For Java 8, they all pass.
– Will Beason
Aug 16 at 13:47



As Rich pointed out in the comments, the problem is using Java 9 or later because they changed how classloaders work. The non-ideal fix is to downgrade to Java 8.



To ensure Java 8 is installed (Linux):


sudo update-alternatives --display java



To default to Java 8:


sudo update-alternatives --config java



After switching to Java 8, everything works fine. The solution is not ideal because it relies on using a version of Java that won't be supported for much longer.





Pleased you found something that works, even if it's non-ideal. I might've thought sbt would be able to handle this somehow, so have added sbt tag.
– theStrawMan
Aug 16 at 23:05





It does sound like an sbt bug. Hopefully someone will post a proper fix here and win some magic internet points.
– Rich
Aug 17 at 14:35



sbt



Edit: See later comment on class-loaders.



I haven't ever had to reference java.sql myself so this is not from personal experience, but it looks like the same problem as in this question: java.lang.SecurityException: error when executing outside Eclipse, where the problem occurs only outside the IDE. Doesn't look like you have your own class or package starting with 'java', so it's not that. What do your classpaths look like? It is a problem with the way the IDE builds with dependencies, so I think will require action within Intellij rather than changing the script - something like this: How to build JARs from Intellij properly.





I'm actually building the JARs with sbt. The Intellij is just for showing the structure. I got the same behavior in an otherwise clean directory. Though for the script, all of the jars should just be downloaded as dependencies, right?
– Will Beason
Aug 14 at 16:30





Ok, are you using an old version of sbt? It looks like some class-loader things changed when Java 9 was introduced.
– theStrawMan
Aug 14 at 23:39






I'm using sbt 1.2.0, the latest stable version.
– Will Beason
Aug 15 at 15:34





Ok, so not sbt. In response to your question "Though for the script, all of the jars should just be downloaded as dependencies, right?", possibly. That would be done like this. I would hope you wouldn't need that for something in the JDK itself, but possibly that's the only approach. Unfortunately I'm not sure there.
– theStrawMan
Aug 16 at 0:18







By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Firebase Auth - with Email and Password - Check user already registered

Dynamically update html content plain JS

How to determine optimal route across keyboard