How to access resource using class loader in Java 9
Asked Answered
T

2

6

I have a gradle project in eclipse. Here is the structure of my project

project structure

I have css resource styleclass.css in scr/main/resources/css. First I tried to access it using

scene.getStylesheets().add("css/styleclass.css"); 

But I was getting warning resource not found. I also tried it by removing module-info.java file. But result is same.

Then I tried it using

String urlString = ComboBoxStyling.class.getClassLoader().getResource("css/styleclass.css").toExternalForm();

Problem is, this line works if I remove moduele-info.java and style sheet applied. But with module-info.java I am getting null pointer exception.

I don't know much but atleast I know that class loader have changes in Java 9. So how can I do the same in Java 9. My module-info.java file contains the following

module pk.training.basit {
    exports pk.training.basit;
    requires transitive javafx.controls;
}

Thanks & Regards

Basit Mahmood Ahmed

Toothless answered 13/2, 2018 at 14:16 Comment(4)
The resource is encapsulated so it can't be found with the ClassLoader APIs. I assume ComboBoxStyling.class..getResource("/css/styleclass.css") will work - note the leading slash so that it is found relative to the root location of the module, not relative to ComboBoxStyling.class in this case.Prescribe
Yup that's work :)Toothless
@Alan Bateman Post your answer so I can accept itToothless
#46862089Chaisson
P
3

From ClassLoader.getResource JavaDoc:

Resources in named modules are subject to the encapsulation rules specified by Module.getResourceAsStream. Additionally, and except for the special case where the resource has a name ending with ".class", this method will only find resources in packages of named modules when the package is opened unconditionally (even if the caller of this method is in the same module as the resource).

So, to fix your issue, you should make the package css open:

module pk.training.basit {
    exports pk.training.basit;
    requires transitive javafx.controls;
    opens css;
}
Prig answered 14/2, 2018 at 15:34 Comment(2)
The original question seems to be code trying to locate its own resource. The ClassLoader API is wrong API for that. With the code changed to invoke getResource on a class in the module then it should work fine, no need to open any packages.Prescribe
@AlanBateman I just answer exactly what the OP asked. What if he has 200 places with getClassLoader().getResource()? So he can just add a single line of code instead of changing those 200 places.Prig
O
2

You should put your css in the same package as the class which uses it, then use Class.getResource to access it, with the relative Path.

src/main/java:
  pk.training.basit
    ComboBoxStyling.java

src/main/resources:
  pk.training.basit
    ComboBoxStyling.css

Then in the source:

scene.getStylesheets().add(
  ComboBoxStyling.class.getResource("ComboBoxStyling.css").toExternalForm());

Personnally I think it's even a better practice to put the css and the class in the same directory, then configure gradle so It can take the resources in the src/main directory. It permits to have an architecture analog to other GUI products (Angular) which places all the resources of a screen including the source in the same directory, the FXML file for example if you had one.

Octillion answered 16/2, 2018 at 15:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.