-
Notifications
You must be signed in to change notification settings - Fork 30
Description
Issue
When jrubyfx_jarify is used to jarify a project that includes FXML, executing the resulting jar file produces an exception about failing to find a .fxml file, even though the .fxml file is in the top-level folder of the jar file.
Example: java.io.FileNotFoundException: classpath:\Demo.fxml
The problem is the path designation "classpath:", which does not work for locating files inside the jar file. When the project is executed directly from the filesystem, it uses a different and correct filesystem path to the .fxml file, and works. If Demo.fxml is in the top-level directory of the jarfile, then a bare "Demo.fxml" is the right way to specify the path&filename (at least where the fxml_loader is concerned).
I'm working on Win10 x64, which is why the path separator in the error message is a backslash instead of a forward slash. Internally, the path is stored with a forward slash, as the example below will show.
Workaround
This workaround involves changes in a couple of places, which work together to address a couple of related things.
The first issue is that the fxml_root is being set to the value "classpath:/". This comes from the main script of the project. For instance, in the jrubyfx gem's Demo.rb script, before the actual application class declaration, there is a line:
fxml_root File.dirname(__FILE__)
When executed from a filesystem, this works fine. When executed from a jarfile, this returns "classpath:/". File.dirname works as it should; the value of FILE in the jar context is, for Demo.rb, "classpath:/Demo.rb".
My workaround is to replace the single fxml_root line with the following:
if JRubyFX::Application.in_jar? then
fxml_root nil, "" # need to set the second parameter, jar_value, to ""
else
fxml_root File.dirname(__FILE__)
end
Presumably, one would do this for the fxml_root declaration in the main script of any FXML project you wish to jarify. When not in a jar, it works as before. When in a jar, it passes different parameters to fxml_root. Setting the second parameter, while leaving the first nil, indicates to fxml_root that the root is inside a jar. Making the jar_value the empty string (helps to) indicate that nothing should be appended to whatever relative path is given for the .fxml file to be loaded. Instead of "classpath:/Demo.fxml", we want "Demo.fxml".
The second change involves the actual construction, later on, of the fxml file location. This occurs in the jrubyfx gem file lib/jrubyfx/controller.rb, where File.join() is used to combine the fxml_root path with the fxml filename. Even though the root_dir has been specified as an empty string, File.join(root_dir, filename) will still prepend a path separator before the filename: instead of "Demo.fxml", we get "/Demo.fxml".
My workaround is to detect when the root_dir is the empty string, and avoid File.join in that circumstance. in lib/jrubyfx/controller.rb, at around line 365, replace the line:
`location = class_loader.call(File.join(root_dir, filename))`
with the following lines:
if (root_dir == "") then
location = class_loader.call(filename)
else
location = class_loader.call(File.join(root_dir, filename))
end