My project is running properly in eclipse but when I am creating a jar file of this project and trying to run it through cmd it is showing \"Location is not set\" error.
My project structure is:
The Method is (Running in eclipse):
@FXML
private void RegularCustomer(ActionEvent event) throws Exception{
Stage stage = (Stage) dailySales.getScene().getWindow();
Scene scene = dailySales.getScene();
FXMLLoader loader = new FXMLLoader(getClass().getResource(\"../customer/CustomerHome.fxml\"));
System.out.println(loader.getLocation());
scene.setRoot(loader.load());
stage.setScene(scene);
stage.show();
}
What is wrong with this code?
There are some relative questions but they are different from it. Their code didn\'t run in IDE but my code run in IDE.
FYI: I made some changes in folder structure and was able to run successfully. But that structure was horrible because I put all my FXML files and controllers in same package.
When you use getClass().getResource(...)
you are loading a resource, not specifying a path to a file. In the case where the class loader loads classes from the file system, these essentially equate to the same thing, and it does actually work (though even then there\'s no technical reason it has to). When the class loader is loading classes by other mechanisms (and probably in all cases anyway), then it\'s important to pay attention to the Java specifications for a resource.
In particular, note:
Resources, names, and contexts
A resource is identified by a string consisting of a sequence of
substrings, delimited by slashes (/), followed by a resource name.
Each substring must be a valid Java identifier. The resource name is of the form shortName or shortName.extension. Both shortName
and extension must be Java identifiers.
(My emphasis.) Since ..
is not a valid Java identifier, there\'s no guarantee of this resource being resolvable. It happens that the file system class loader resolves this in the way you expect, which is why it works in your IDE, but the implementation of getResource(...)
in the jar class loader does not implement this in the way you are hoping.
Try
FXMLLoader loader = new FXMLLoader(getClass().getResource(\"/sm/customer/CustomerHome.fxml\"));
Using controller locations to load FXML:
Since you have organized your code so that each FXML is in the same package as its corresponding controller file (which I think is a sensible way to do things), you could also leverage this in loading the FXML: just load the FXML \"relative to its controller\":
FXMLLoader loader = new FXMLLoader(CustomerHomeCtrl.class.getResource(\"CustomerHome.fxml\"));
This seems fairly natural in this setup, and the compiler will check that you have the package name for CustomerHomeCtrl
correct at the point where you import the class. It also makes it easy to refactor: for example suppose you wanted to split sm.admin
into multiple subpackages. In Eclipse you would create the subpackages, drag and drop the FXML and controllers to the appropriate subpackages, and the import statements would automatically be updated: there would be no further changes needed. In the case where the path is specified in the getResource(...)
, all those would have to be changed by hand.