Jar in external libraries but cannot import in code

(more info at bottom)

I am using Maven to fetch the MySQL Connector for java

dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.16</version>
</dependency>

As such, it shows up in my External Libraries (intellij)

screenshot of external libraries (intellij)

However, in my code, I cannot import java.sql.*, as java.sql is not an option.

screenshot of failed java.sql import

In addition, I have made sure that my Project Structure is correct, having the dependency set as Compile scope

screenshot of project structure

I have also invalidated cache.

I have been stuck on this issue for a bit and cannot find a resolution; any help is appreciated.

More info: java.sql
Works in java 8 projects
Works in blank java 12 projects (not created with openjfx 12 archetype)

Inside main I now have this line of code:

java.sql.Connection c = null;

The error message I get when running is:

Error:(37, 9) java: package java.sql is not visible
  (package java.sql is declared in module java.sql, but module com.github.phaserush does not read it)

Solution:

The error indicates you are using the Java module system, and the java.sql module (containing packages java.sql and javax.sql) is not part of the default set of modules loaded by Java. You will need to explicitly depend on it.

In your src/main/java edit your module-info.java and add requires java.sql;. For example:

module com.github.phaserush {
    requires java.sql;
}

Where com.github.phaserush is your module name based on the exception message in your question.

Securely Export Packages to Java Modules

I was answering this question, where I recommended utilizing exports to syntax to prevent external consumers from accessing code that is intended for internal use between modules.

But on further reflection, the only real safety checking that modules implement is that it matches the name. Consider this example where I am implementing two modules:

module com.my.a {
    exports com.my.unsafe to com.my.b
}

module com.my.b {
    requires com.my.a
}

The package com.my.unsafe contains code that would be unsafe to have exposed. Is there any way to securely export this to internal modules without exposing them externally?

In the above example, a rogue entity could simply name their module com.my.b and would gain access to the code (not secure). The JLS doesn’t seem to spell out anything that can prevent it.

Solution:

The hashing of modules as pointed by Alan shall work in your case. Though I personally like the description and the example from the JMOD tool which directly answers your question :

With the --hash-modules option or the jmod hash command, you can, in
each module’s descriptor, record hashes of the content of the modules
that are allowed to depend upon it, thus “tying” together these
modules.

This lets you to allow a package to be exported to one or
more specifically-named modules and to no others through qualified
exports
. The runtime verifies if the recorded hash of a module matches
the one resolved at run time; if not, the runtime returns an error.

How is Java 9 running code compiled with Java 8 that is using a non-exported package

I compiled following code using Java-8 compiler:

package pack;
import sun.util.calendar.CalendarUtils;
public class A {
    public static void main(String[] args) {
        System.out.println(CalendarUtils.isGregorianLeapYear(2018));
    }
}

I compiled the above code using Java-8 compiler as:

gyan@gyan-pc:~/codes/java$ ~/Documents/softwares/Linux/jdk1.8.0_131/bin/javac -d . a.java
a.java:2: warning: CalendarUtils is internal proprietary API and may be removed in a future release
import sun.util.calendar.CalendarUtils;
                        ^
a.java:9: warning: CalendarUtils is internal proprietary API and may be removed in a future release
        System.out.println(CalendarUtils.isGregorianLeapYear(2018));
                           ^
2 warnings

Version of my default Java Interpreter:

gyan@gyan-pc:~/codes/java$ java -version
java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

And I can run the compiled code using Java-9 interpreter without any error.

gyan@gyan-pc:~/codes/java$ java pack.a
false

According to my knowledge: At runtime the package “pack” will be contained inside a special module called “Unnamed module”. The “Unnamed module” requires all the modules from Java platform module. But only that package can be used by the “Unnamed module” which are exported by the corresponding module.

My question is:
Here the module java.base is not exporting the package “sun.util.calendar”. Then how the “Unnamed module” is using it?

Solution:

As pointed by Alan, the section Relaxed strong encapsulation states the following in this respect :-

--illegal-access=permit opens each package in each module in the run-time image to code in all unnamed modules, i.e., to code on the
class path, if that package existed in JDK 8. This enables both static
access, i.e., by compiled bytecode, and deep reflective access, via
the platform’s various reflection APIs.

The first reflective-access operation to any such package causes a
warning to be issued, but no warnings are issued after that point.
This single warning describes how to enable further warnings. This
warning cannot be suppressed.

This mode is the default in JDK 9. It will be phased out in a future
release and, eventually, removed.

Also, if you try to execute the compiled code with

.../jdk-9.0.1.jdk/Contents/Home/bin/java --illegal-access=deny pack.Some

using the future default flag, you wouldn’t be able to execute the code as expected with the following trace :

Exception in thread "main" java.lang.IllegalAccessError: class
pack.Some (in unnamed module @0x1055e4af) cannot access class
sun.util.calendar.CalendarUtils (in module java.base) because module
java.base does not export sun.util.calendar to unnamed module
@0x1055e4af    at pack.Some.main(Some.java:7)

JAVA ERROR : package com.sun.rowset is not visible : com.sun.rowset is declared in module java.sql.rowset, which does not export it

I’m simply try to run this code:

import com.sun.rowset.CachedRowSetImpl;

public class Test {
    public static void main(String[] args) throws Exception{
        CachedRowSetImpl crs = new CachedRowSetImpl();
    }
}

When I run it I get:

Error:(1, 15) java: package com.sun.rowset is not visible (package
com.sun.rowset is declared in module java.sql.rowset, which does not
export it)

I’m using IntelliJ and I tried to import rs2xml.jar, and that still doesnt help.

Solution:

With Java 9 you can not access this class anymore. And in the ideal way you shouldn’t do that. That is because this class’s package is not exported in the module javax.sql.rowset. The proper way to do that in Java-9 will be:

import javax.sql.rowset.*; 

public class Test {
    public static void main(String[] args) throws Exception {

        CachedRowSet crs = RowSetProvider.newFactory().createCachedRowSet();
    }
}

To understand that we can go to the module description (module-info.java) and find a list of exported packages:

exports javax.sql.rowset;
exports javax.sql.rowset.serial;
exports javax.sql.rowset.spi;