Loading Resources with absolute path from Classpath

I need to Load resources with absolute path from all modules that are present. Example: I have the following modules: * com.example.appmanager * com.example.demoapp * com.example.utilscreens And I want to load /com/example/appmanger/base.fxml as well as /com/example/demoapp/MainScreen.fxml from a class in com.example.appmanager. No matter What I try it does not find the resources. Here is my code for finding the resource:
for (Module mod : ModuleLayer.boot().modules())
if(mod.getName().startsWith(prefix)) {
log.debug(mod.getName());
try {
log.debug(String.valueOf(mod.getResourceAsStream(resource)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
for (Module mod : ModuleLayer.boot().modules())
if(mod.getName().startsWith(prefix)) {
log.debug(mod.getName());
try {
log.debug(String.valueOf(mod.getResourceAsStream(resource)));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
For now it only prints the URL, but that would be sufficient for a demo. Any hints for a better way to do this, or hints what I am doing wrong or a solution would be greatly apreciated.
64 Replies
JavaBot
JavaBot7mo ago
This post has been reserved for your question.
Hey @NeoCortex97! Please use /close or the Close Post button above when your problem is solved. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.
TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.
NeoCortex97
NeoCortex97OP7mo ago
I don't really want to write an annotation processor to calculate everything, or use a maven setup to copy the resources around. But if it makes that simpler or even feasable at all, im going to do that.
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
I have this code in a abstract class in com.example.appmanager and my demo applcation is extending this class. So I don't know if i am loading from a jar.
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
My intention is to store everything inside the jar, but i might need to do some magic, so the resources from the appmanager library are included too.
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
would it be possible, if i knew a class inside the corresponding module that i use this Class object to get the resource from it? I am using org.reflections to do runtime reflections as a measure of discovering the loadable fmxl files by annotating the controllers.
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
I meant somthing like controllerClass.getResource(resource); I just want to discover fxml files. the fxml knows its controller, but i cant annotate the fxml, so i am using reflections to discover all classes that are annotated with a special marker annotation
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
I am writing my own Framework (I know you shouldn't necessarily do that) that handles boilerplate. My Intention was the following:
@Screen("./MainScreen.fxml", visible = true)
public class MainScreenController extends ScreenController {
// Pure javafx controller code
}
@Screen("./MainScreen.fxml", visible = true)
public class MainScreenController extends ScreenController {
// Pure javafx controller code
}
I discover the screen annotation and build the absolute path of the resource from the module of the controller and the value in the annotation. If it is a debug screen, it will be invisible unless there is a debug flag on the commandline if the visible property is set to false. visible should be called debug tho and should work opposite. But that is not an issue. The discovery works flawlessly.
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
I am only discovering the controller classes to get the fxml files and just discard the Class objects for the controllers after that. I have a fixed RootScreen that has MenuBar, StatusBar and some other nice things. I want to inject the loaded Screens into the sceene graph of this root screen and extract Settings definitions, Menu Items from the Screen controllers. And i want to inject Services and a ScreenRegistry utility class to switch between screens and some other utilites that allow for a few pretty complex things without writing that boilerplate everywhere. I am only discovering the Class definitions, not creating any instances. When the fxml is loaded, i use getController to get an instance of the controller and do my extraction and injection on that.
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
I know, that I could include that, but I think it would be complex to dynamically add includes to the fxml files. I am dynamically load the root screen as well, so that a user could exchange the root screen as well, if he wants an extra toolbar, or a ribbon. He is me using my framework later
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
Very ambitious indeed. Could I make my resources in appmanager visible to the demo app somehow? Like with manifest files?
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
I'll try to implement opening jars as filesystems. Do you know from the top of your head if that still works with fat jars?
Unknown User
Unknown User7mo ago
Message Not Public
Sign In & Join Server To View
NeoCortex97
NeoCortex97OP7mo ago
I'll experiment a little an would report back if I stumble into problems later
stechy1
stechy17mo ago
@NeoCortex97 Hello, have you figured out how to discover all resources? I did exactly same thing in my framework for JFX so if you need any help, you can ping me 🙂 It seems that we are creating similiar framework for better controller/screen management...
NeoCortex97
NeoCortex97OP7mo ago
Here is your ping. 😅 I did not really achieve a lot by now. I just tried some things I've read on stack overflow. Nothing really worked. Did you publish your framework? Maybe I took a look for inspiration. I am creating one to match the style our backend code at work looks and we are using spring boot. But I didn't want to spin up a whole spring boot context, because it would be too tempting to bypass a proper backend. So I am building a "Magic and Annotations" style framework that feels a little like spring boot with better errors and auto detection on everything.
stechy1
stechy17mo ago
@NeoCortex97 I have not publish it yet. I can give you an access if you want, but it is quite a big project now. But regarding the resources. I would advise you support loading resources from "normal folders" mainly for development purposes and also from "jars" for production. you have the project public?
NeoCortex97
NeoCortex97OP7mo ago
Not yet, but I will as soon as I have a working prototype.... Or maybe before that.
NeoCortex97
NeoCortex97OP7mo ago
I am currently thinking of making a base application and just implementing every screen as a plugin, but I think that would be excessive. I might use a plugin framework behind the scenes tho. https://pf4j.org/ Pf4j manages the class loaders and loading shit from jars, zip files, folders.... I'll try at least, because plugin loading will be another feature of my framework, but rather high level and when everything else is working
PF4J
PF4J
PF4J site repository
stechy1
stechy17mo ago
Oh, that looks good. Maybe you can try advantage of the framework for loading resources...
JavaBot
JavaBot7mo ago
💤 Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived. If your question was not answered yet, feel free to re-open this post or create a new one. In case your post is not getting any attention, you can try to use /help ping. Warning: abusing this will result in moderative actions taken against you.
NeoCortex97
NeoCortex97OP7mo ago
I am planning to try the following. Ill write it down here, so i dont forget half ways. Ill create a ScreenLoader Class that takes care of loading an fxml file within the context the controller sits in. that should work normal. I could even generate these Loaders automagically with a custom source code generator as a maven Plugin. Otherwise coding the loader classes would add boilerplate - which I am trying to remove. PF4J has "Extension Points" to mark different parts of your internal api as acessible by a plugin. Later you can tell PF4J to fetch you all implementetions of your extension point. So I would need to declare an interface that my Loader would implement, so i could get Loaders for all my Screens. I would need to repeat that thing for views and RootScreens too. I diferentiate Screens as something that should be displayed standalone and make sense, but without any global state or controls. RootScreens are Containers to put screens in, but just MenuBar, StatusBar, and a container for a screen. Views are UIs, that don't make sense if displayed Standalone, like Uis in a List, popups, or things subviews. I also want to manage Services, For background activities, like sending data to a Rest endpoint, performing operations in the background,... My current code for that works fine, but i think reimplementing them as extension points would be a good choice.
NeoCortex97
NeoCortex97OP7mo ago
I will likely add some components for some fancy components to my default RootScreen. DialogPane and DrawerStackPane from gemsfx (https://github.com/dlsc-software-consulting-gmbh/GemsFX) NotificationPane, Notification, TaskProgressView and PopOver from ControlsFX (https://controlsfx.github.io/) Ill use PopOver and TaskProgressView To show status of backgroundTasks in Progress and integrate that in my RootScreen. I will use these things anyways and having them and not using them at the Moment is not an issue for me, but needing to inject them later from a screen would be rather annoying, since most would require modifying the scenegraph and that is expensive.
GitHub
GitHub - dlsc-software-consulting-gmbh/GemsFX: A collection of Java...
A collection of JavaFX controls and utilities. Contribute to dlsc-software-consulting-gmbh/GemsFX development by creating an account on GitHub.
stechy1
stechy17mo ago
For your first point. Do you know how ServiceLoader works in Java? With that you can achieve exactly the same result as PF4J - get every available implementation of some interface. The only difference is that PF4J can load it in runtime and ServiceLoader can load only classes on classpath/modulepath ping
NeoCortex97
NeoCortex97OP7mo ago
I did already read about it and I would just use pf4j, since im planning to support plugins anyways.
stechy1
stechy17mo ago
And just one advice: use as few dependencies as possible. It could discourse others from using it
NeoCortex97
NeoCortex97OP7mo ago
I'm just using the dependencies I'm using anyways. I'm mainly planning to use it proivately and for work. But when everything works i might try to remove as many mandatory dependencies as possible.
stechy1
stechy17mo ago
I'm pointing to dependencies for GemsFX and ControlsFX
NeoCortex97
NeoCortex97OP7mo ago
I know. Since it is mainly for me and for my work where we also use these anyways it doesn't matter. But when I'm publishing it, i will implement it in a way that only uses these libraries if you add them as dependencies.
stechy1
stechy17mo ago
Yeah, that's cool. I just know from my practice that it is harder to remove integrated dependency than never count with it 😀
NeoCortex97
NeoCortex97OP7mo ago
They are purely used in the RootScreen, so I think it won't be too hard. But I know how hard it is to get rid of dependencies. Id dod on several projects before 😄
stechy1
stechy17mo ago
So, have you progressed with loading resources?
NeoCortex97
NeoCortex97OP7mo ago
A bit. Using AppManager.class.getResource() I can load my default screens and my RootScreens.
stechy1
stechy17mo ago
This can work only for resources within the same jar file. So AppManager will not be able to load screens from plugins
NeoCortex97
NeoCortex97OP7mo ago
Sure, but it is a progress. I'm not finished implementing the plugin system into the AppManager. Okay, I officially admit, that I am dumb. I can load the RootScreen, but i cant show the window.
stechy1
stechy17mo ago
Why you can't show it? 😃
NeoCortex97
NeoCortex97OP7mo ago
It is unable to load the StatusBar... I think I either need to set up shading for my AppManager, or write my own status bar. Or just start over and implement the plugin system from the ground up. I actually could implement the root screen as a plugin as well. That would remove the dependency of gemsfx and controlsfx from my library and would make for simpler implementation of a custom RootScreen
stechy1
stechy17mo ago
Yep, that could be a way to go I have done it more or less in the same way I'm loading everything with a service loader...
NeoCortex97
NeoCortex97OP7mo ago
Did you subclass the javafx application class, or do you have a class that you pass your application class into to configure everything?
stechy1
stechy17mo ago
My framework has its own abstract class which inherits javafx application
NeoCortex97
NeoCortex97OP7mo ago
Mine does that too, so I'm not that far off.
stechy1
stechy17mo ago
It also has support for a Preloader... Where I can do for example loading of all resources and inform the user about progress
NeoCortex97
NeoCortex97OP7mo ago
Basically a splash screen?
stechy1
stechy17mo ago
Yeah JavaFX has built in some basic support
NeoCortex97
NeoCortex97OP7mo ago
Okay, that makes sense. I will eventually do that correctly, but until then I will use the updater I wrote for my last project
stechy1
stechy17mo ago
I've been working on the framework for almost 5 years now. I made many mistakes, but now it looks quite good and usable... I'm writing a documentation for it now... But still see a lot of space for improvement
NeoCortex97
NeoCortex97OP7mo ago
I restarted and implemented a minimal RootScreen for now, so I have something to load and look at. I am going to implement the AppManager with the plugin System now. I think I will just implement a getter for the RootScreen, so it is accessible to the user. My content root is a Pane and I set my content as the child for the pane.
stechy1
stechy17mo ago
I find out that StackPane is much better in this context. It allows you to use for example layers In a Pane, you have to set positions statically and static is not good 😉
NeoCortex97
NeoCortex97OP7mo ago
I have a StackPane with a VBox. The VBox contains MenuBar, Pane and StatusBar. That pane is my content root. It's only job is to contain my Screen content
stechy1
stechy17mo ago
Then StackPane has no use if it only contains VBox or I miss something?
NeoCortex97
NeoCortex97OP7mo ago
It also contains DrawerStackPane and DialogPane.
stechy1
stechy17mo ago
Oh okay 👍 So this is somehow predefined for every application which will use your framework...
NeoCortex97
NeoCortex97OP7mo ago
I will implement an extension for the RootScreen, so you can customize it if you want to. But it's supposed to be predefined if you use the default RootScreen. Normally you would be supposed to do this setup on every screen.
stechy1
stechy17mo ago
I see. The idea is to have a base layout for all your windows including styles, fonts and others in one single place
NeoCortex97
NeoCortex97OP7mo ago
Yes, exactly. It should manage menu Items, icons for the status bar, the drawer and the Dialog pane. I really like the Dialog pane from gemsfx. It is a transparent pane when it is not needed. It is supposed to sit on top of the content and is click through. Except when it is active. I that case it shows it's contents within the same window. In my case I am writing kiosk mode apps anyways and we experienced very skillful customers that managed to close our application when a dialog is open. Even with the customers we were not able to reproduce it later, but that can't happen with the gemsfx dialog pane.
JavaBot
JavaBot7mo ago
💤 Post marked as dormant
This post has been inactive for over 300 minutes, thus, it has been archived. If your question was not answered yet, feel free to re-open this post or create a new one. In case your post is not getting any attention, you can try to use /help ping. Warning: abusing this will result in moderative actions taken against you.
Want results from more Discord servers?
Add your server